use of org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateTenantRequest in project ozone by apache.
the class OMTenantCreateRequest method validateAndUpdateCache.
@Override
@SuppressWarnings("methodlength")
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, long transactionLogIndex, OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) {
final OMMultiTenantManager multiTenantManager = ozoneManager.getMultiTenantManager();
final OMMetrics omMetrics = ozoneManager.getMetrics();
omMetrics.incNumTenantCreates();
omMetrics.incNumVolumeCreates();
OMClientResponse omClientResponse = null;
final OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(getOmRequest());
OmVolumeArgs omVolumeArgs;
boolean acquiredVolumeLock = false;
boolean acquiredUserLock = false;
final String owner = getOmRequest().getUserInfo().getUserName();
Map<String, String> auditMap = new HashMap<>();
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
final CreateTenantRequest request = getOmRequest().getCreateTenantRequest();
final String tenantId = request.getTenantId();
final String userRoleName = request.getUserRoleName();
final String adminRoleName = request.getAdminRoleName();
final VolumeInfo volumeInfo = getOmRequest().getCreateVolumeRequest().getVolumeInfo();
final String volumeName = volumeInfo.getVolume();
Preconditions.checkNotNull(volumeName);
Preconditions.checkState(request.getVolumeName().equals(volumeName), "CreateTenantRequest's volumeName value should match VolumeInfo's");
final String dbVolumeKey = omMetadataManager.getVolumeKey(volumeName);
IOException exception = null;
try {
// Check ACL: requires volume CREATE permission.
if (ozoneManager.getAclsEnabled()) {
checkAcls(ozoneManager, OzoneObj.ResourceType.VOLUME, OzoneObj.StoreType.OZONE, IAccessAuthorizer.ACLType.CREATE, tenantId, null, null);
}
acquiredVolumeLock = omMetadataManager.getLock().acquireWriteLock(VOLUME_LOCK, volumeName);
// Check volume existence
if (omMetadataManager.getVolumeTable().isExist(dbVolumeKey)) {
LOG.debug("volume: '{}' already exists", volumeName);
throw new OMException("Volume already exists", VOLUME_ALREADY_EXISTS);
}
// Create volume
acquiredUserLock = omMetadataManager.getLock().acquireWriteLock(USER_LOCK, owner);
// TODO: dedup OMVolumeCreateRequest
omVolumeArgs = OmVolumeArgs.getFromProtobuf(volumeInfo);
omVolumeArgs.setObjectID(ozoneManager.getObjectIdFromTxId(transactionLogIndex));
omVolumeArgs.setUpdateID(transactionLogIndex, ozoneManager.isRatisEnabled());
// Set volume reference count to 1
omVolumeArgs.incRefCount();
Preconditions.checkState(omVolumeArgs.getRefCount() == 1, "refCount should have been set to 1");
// Audit
auditMap = omVolumeArgs.toAuditMap();
PersistedUserVolumeInfo volumeList;
final String dbUserKey = omMetadataManager.getUserKey(owner);
volumeList = omMetadataManager.getUserTable().get(dbUserKey);
volumeList = addVolumeToOwnerList(volumeList, volumeName, owner, ozoneManager.getMaxUserVolumeCount(), transactionLogIndex);
createVolume(omMetadataManager, omVolumeArgs, volumeList, dbVolumeKey, dbUserKey, transactionLogIndex);
LOG.debug("volume: '{}' successfully created", dbVolumeKey);
// Check tenant existence in tenantStateTable
if (omMetadataManager.getTenantStateTable().isExist(tenantId)) {
LOG.debug("tenant: '{}' already exists", tenantId);
throw new OMException("Tenant already exists", TENANT_ALREADY_EXISTS);
}
// Create tenant
// Add to tenantStateTable. Redundant assignment for clarity
final String bucketNamespaceName = volumeName;
// Populate policy ID list
final String bucketNamespacePolicyName = OMMultiTenantManager.getDefaultBucketNamespacePolicyName(tenantId);
final String bucketPolicyName = OMMultiTenantManager.getDefaultBucketPolicyName(tenantId);
final OmDBTenantState omDBTenantState = new OmDBTenantState(tenantId, bucketNamespaceName, userRoleName, adminRoleName, bucketNamespacePolicyName, bucketPolicyName);
omMetadataManager.getTenantStateTable().addCacheEntry(new CacheKey<>(tenantId), new CacheValue<>(Optional.of(omDBTenantState), transactionLogIndex));
// Update tenant cache
multiTenantManager.getCacheOp().createTenant(tenantId, userRoleName, adminRoleName);
omResponse.setCreateTenantResponse(CreateTenantResponse.newBuilder().build());
omClientResponse = new OMTenantCreateResponse(omResponse.build(), omVolumeArgs, volumeList, omDBTenantState);
} catch (IOException ex) {
omClientResponse = new OMTenantCreateResponse(createErrorOMResponse(omResponse, ex));
exception = ex;
} finally {
addResponseToDoubleBuffer(transactionLogIndex, omClientResponse, ozoneManagerDoubleBufferHelper);
if (acquiredUserLock) {
omMetadataManager.getLock().releaseWriteLock(USER_LOCK, owner);
}
if (acquiredVolumeLock) {
omMetadataManager.getLock().releaseWriteLock(VOLUME_LOCK, volumeName);
}
// Release authorizer write lock
multiTenantManager.getAuthorizerLock().unlockWriteInOMRequest();
}
// Perform audit logging
auditMap.put(OzoneConsts.TENANT, tenantId);
// Note auditMap contains volume creation info
auditLog(ozoneManager.getAuditLogger(), buildAuditMessage(OMAction.CREATE_TENANT, auditMap, exception, getOmRequest().getUserInfo()));
// Log CREATE_VOLUME as well since a volume is created
auditLog(ozoneManager.getAuditLogger(), buildAuditMessage(OMAction.CREATE_VOLUME, auditMap, exception, getOmRequest().getUserInfo()));
if (exception == null) {
LOG.info("Created tenant '{}' and volume '{}'", tenantId, volumeName);
omMetrics.incNumTenants();
omMetrics.incNumVolumes();
} else {
LOG.error("Failed to create tenant '{}'", tenantId, exception);
omMetrics.incNumTenantCreateFails();
}
return omClientResponse;
}
use of org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateTenantRequest in project ozone by apache.
the class OMTenantCreateRequest method preExecute.
@Override
@DisallowedUntilLayoutVersion(MULTITENANCY_SCHEMA)
public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
final OMMultiTenantManager multiTenantManager = ozoneManager.getMultiTenantManager();
// Check Ozone cluster admin privilege
multiTenantManager.checkAdmin();
final OMRequest omRequest = super.preExecute(ozoneManager);
final CreateTenantRequest request = omRequest.getCreateTenantRequest();
Preconditions.checkNotNull(request);
final String tenantId = request.getTenantId();
// Check tenantId validity
if (tenantId.contains(OzoneConsts.TENANT_ID_USERNAME_DELIMITER)) {
throw new OMException("Invalid tenant name " + tenantId + ". Tenant name should not contain delimiter.", OMException.ResultCodes.INVALID_VOLUME_NAME);
}
// Check tenant existence in tenantStateTable
if (ozoneManager.getMetadataManager().getTenantStateTable().isExist(tenantId)) {
LOG.debug("tenant: {} already exists", tenantId);
throw new OMException("Tenant '" + tenantId + "' already exists", TENANT_ALREADY_EXISTS);
}
// getUserName returns:
// - Kerberos principal when Kerberos security is enabled
// - User's login name when security is not enabled
// - AWS_ACCESS_KEY_ID if the original request comes from S3 Gateway.
// Not Applicable to TenantCreateRequest.
final UserGroupInformation ugi = ProtobufRpcEngine.Server.getRemoteUser();
// getShortUserName here follows RpcClient#createVolume
// A caveat is that this assumes OM's auth_to_local is the same as
// the client's. Maybe move this logic to the client and pass VolumeArgs?
final String owner = ugi.getShortUserName();
// Volume name defaults to tenant name if unspecified in the request
final String volumeName = request.getVolumeName();
// Validate volume name
OmUtils.validateVolumeName(volumeName);
// TODO: Refactor this and OMVolumeCreateRequest to improve maintainability.
final VolumeInfo volumeInfo = VolumeInfo.newBuilder().setVolume(volumeName).setAdminName(owner).setOwnerName(owner).build();
// Generate volume modification time
long initialTime = Time.now();
final VolumeInfo updatedVolumeInfo = volumeInfo.toBuilder().setCreationTime(initialTime).setModificationTime(initialTime).build();
final String userRoleName = OMMultiTenantManager.getDefaultUserRoleName(tenantId);
final String adminRoleName = OMMultiTenantManager.getDefaultAdminRoleName(tenantId);
// Acquire write lock to authorizer (Ranger)
multiTenantManager.getAuthorizerLock().tryWriteLockInOMRequest();
try {
// Create tenant roles and policies in Ranger.
// If the request fails for some reason, Ranger background sync thread
// should clean up any leftover policies and roles.
multiTenantManager.getAuthorizerOp().createTenant(tenantId, userRoleName, adminRoleName);
} catch (Exception e) {
multiTenantManager.getAuthorizerLock().unlockWriteInOMRequest();
throw e;
}
final OMRequest.Builder omRequestBuilder = omRequest.toBuilder().setCreateTenantRequest(CreateTenantRequest.newBuilder().setTenantId(tenantId).setVolumeName(volumeName).setUserRoleName(userRoleName).setAdminRoleName(adminRoleName)).setCreateVolumeRequest(CreateVolumeRequest.newBuilder().setVolumeInfo(updatedVolumeInfo));
return omRequestBuilder.build();
}
Aggregations