in hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantAssignUserAccessIdRequest.java [190:361]
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) {
final long transactionLogIndex = context.getIndex();
final OMMultiTenantManager multiTenantManager =
ozoneManager.getMultiTenantManager();
final OMMetrics omMetrics = ozoneManager.getMetrics();
omMetrics.incNumTenantAssignUsers();
OMClientResponse omClientResponse = null;
final OMResponse.Builder omResponse =
OmResponseUtil.getOMResponseBuilder(getOmRequest());
final UpdateGetS3SecretRequest updateGetS3SecretRequest =
getOmRequest().getUpdateGetS3SecretRequest();
final String accessId = updateGetS3SecretRequest.getKerberosID();
final String awsSecret = updateGetS3SecretRequest.getAwsSecret();
boolean acquiredVolumeLock = false;
final Map<String, String> auditMap = new HashMap<>();
final OMMetadataManager omMetadataManager =
ozoneManager.getMetadataManager();
final TenantAssignUserAccessIdRequest request =
getOmRequest().getTenantAssignUserAccessIdRequest();
final String tenantId = request.getTenantId();
final String userPrincipal = request.getUserPrincipal();
Preconditions.checkState(accessId.equals(request.getAccessId()));
Exception exception = null;
String volumeName = null;
try {
volumeName = ozoneManager.getMultiTenantManager()
.getTenantVolumeName(tenantId);
mergeOmLockDetails(omMetadataManager.getLock().acquireWriteLock(
VOLUME_LOCK, volumeName));
acquiredVolumeLock = getOmLockDetails().isLockAcquired();
// Expect tenant existence in tenantStateTable
if (!omMetadataManager.getTenantStateTable().isExist(tenantId)) {
LOG.error("tenant {} doesn't exist", tenantId);
throw new OMException("tenant '" + tenantId + "' doesn't exist",
ResultCodes.TENANT_NOT_FOUND);
}
// Expect accessId absence from tenantAccessIdTable
if (omMetadataManager.getTenantAccessIdTable().isExist(accessId)) {
LOG.error("accessId {} already exists", accessId);
throw new OMException("accessId '" + accessId + "' already exists!",
ResultCodes.TENANT_USER_ACCESS_ID_ALREADY_EXISTS);
}
OmDBUserPrincipalInfo principalInfo = omMetadataManager
.getPrincipalToAccessIdsTable().getIfExist(userPrincipal);
// Reject if the user is already assigned to the tenant
if (principalInfo != null) {
// If any existing accessIds are assigned to the same tenant, throw ex
// TODO: There is room for perf improvement. add a map in OMMTM.
for (final String existingAccId : principalInfo.getAccessIds()) {
final OmDBAccessIdInfo accessIdInfo =
omMetadataManager.getTenantAccessIdTable().get(existingAccId);
if (accessIdInfo == null) {
LOG.error("Metadata error: accessIdInfo is null for accessId '{}'. "
+ "Ignoring.", existingAccId);
throw new OMException("accessIdInfo is null",
ResultCodes.INVALID_ACCESS_ID);
}
if (tenantId.equals(accessIdInfo.getTenantId())) {
throw new OMException("The same user is not allowed to be assigned "
+ "to the same tenant more than once. User '" + userPrincipal
+ "' is already assigned to tenant '" + tenantId + "' with "
+ "accessId '" + existingAccId + "'.",
ResultCodes.TENANT_USER_ACCESS_ID_ALREADY_EXISTS);
}
}
}
final S3SecretValue s3SecretValue = S3SecretValue.of(accessId, awsSecret, transactionLogIndex);
// Add to tenantAccessIdTable
final OmDBAccessIdInfo omDBAccessIdInfo = new OmDBAccessIdInfo.Builder()
.setTenantId(tenantId)
.setUserPrincipal(userPrincipal)
.setIsAdmin(false)
.setIsDelegatedAdmin(false)
.build();
omMetadataManager.getTenantAccessIdTable().addCacheEntry(
new CacheKey<>(accessId),
CacheValue.get(transactionLogIndex, omDBAccessIdInfo));
// Add to principalToAccessIdsTable
if (principalInfo == null) {
principalInfo = new OmDBUserPrincipalInfo.Builder()
.setAccessIds(new TreeSet<>(Collections.singleton(accessId)))
.build();
} else {
principalInfo.addAccessId(accessId);
}
omMetadataManager.getPrincipalToAccessIdsTable().addCacheEntry(
new CacheKey<>(userPrincipal),
CacheValue.get(transactionLogIndex, principalInfo));
// Expect accessId absence from S3SecretTable
ozoneManager.getS3SecretManager()
.doUnderLock(accessId, s3SecretManager -> {
if (s3SecretManager.hasS3Secret(accessId)) {
LOG.error("accessId '{}' already exists in S3SecretTable",
accessId);
throw new OMException("accessId '" + accessId +
"' already exists in S3SecretTable",
ResultCodes.TENANT_USER_ACCESS_ID_ALREADY_EXISTS);
}
s3SecretManager
.updateCache(accessId, s3SecretValue);
return null;
});
// Update tenant cache
multiTenantManager.getCacheOp()
.assignUserToTenant(userPrincipal, tenantId, accessId);
// Generate response
omResponse.setTenantAssignUserAccessIdResponse(
TenantAssignUserAccessIdResponse.newBuilder()
.setS3Secret(S3Secret.newBuilder()
.setAwsSecret(awsSecret).setKerberosID(accessId))
.build());
omClientResponse = new OMTenantAssignUserAccessIdResponse(
omResponse.build(), s3SecretValue, userPrincipal,
accessId, omDBAccessIdInfo, principalInfo,
ozoneManager.getS3SecretManager());
} catch (IOException | InvalidPathException ex) {
exception = ex;
omResponse.setTenantAssignUserAccessIdResponse(
TenantAssignUserAccessIdResponse.newBuilder().build());
omClientResponse = new OMTenantAssignUserAccessIdResponse(
createErrorOMResponse(omResponse, exception));
} finally {
if (acquiredVolumeLock) {
Preconditions.checkNotNull(volumeName);
mergeOmLockDetails(
omMetadataManager.getLock().releaseWriteLock(VOLUME_LOCK,
volumeName));
}
// Release authorizer write lock
multiTenantManager.getAuthorizerLock().unlockWriteInOMRequest();
if (omClientResponse != null) {
omClientResponse.setOmLockDetails(getOmLockDetails());
}
}
// Audit
auditMap.put(OzoneConsts.TENANT, tenantId);
auditMap.put("user", userPrincipal);
auditMap.put("accessId", accessId);
markForAudit(ozoneManager.getAuditLogger(), buildAuditMessage(
OMAction.TENANT_ASSIGN_USER_ACCESSID, auditMap, exception,
getOmRequest().getUserInfo()));
if (exception == null) {
LOG.info("Assigned user '{}' to tenant '{}' with accessId '{}'",
userPrincipal, tenantId, accessId);
} else {
LOG.error("Failed to assign '{}' to tenant '{}' with accessId '{}': {}",
userPrincipal, tenantId, accessId, exception.getMessage());
omMetrics.incNumTenantAssignUserFails();
}
return omClientResponse;
}