use of org.apache.hadoop.ozone.om.helpers.OmDBTenantState 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.om.helpers.OmDBTenantState in project ozone by apache.
the class OMTenantDeleteRequest 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.incNumTenantDeletes();
OMClientResponse omClientResponse = null;
final OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(getOmRequest());
boolean acquiredVolumeLock = false;
final Map<String, String> auditMap = new HashMap<>();
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
final DeleteTenantRequest request = getOmRequest().getDeleteTenantRequest();
final String tenantId = request.getTenantId();
String volumeName = null;
boolean decVolumeRefCount = true;
IOException exception = null;
OmVolumeArgs omVolumeArgs = null;
try {
// Check tenant existence in tenantStateTable
if (!omMetadataManager.getTenantStateTable().isExist(tenantId)) {
LOG.debug("tenant: {} does not exist", tenantId);
throw new OMException("Tenant '" + tenantId + "' does not exist", TENANT_NOT_FOUND);
}
// Reading the TenantStateTable without lock as we don't have or need
// a TENANT_LOCK. The assumption is that OmDBTenantState is read-only
// once it is set during tenant creation.
final OmDBTenantState dbTenantState = omMetadataManager.getTenantStateTable().get(tenantId);
volumeName = dbTenantState.getBucketNamespaceName();
Preconditions.checkNotNull(volumeName);
LOG.debug("Tenant '{}' has volume '{}'", tenantId, volumeName);
// decVolumeRefCount is true if volumeName is not empty string
decVolumeRefCount = volumeName.length() > 0;
// Acquire the volume lock
acquiredVolumeLock = omMetadataManager.getLock().acquireWriteLock(VOLUME_LOCK, volumeName);
// Check if there are any accessIds in the tenant
if (!ozoneManager.getMultiTenantManager().isTenantEmpty(tenantId)) {
LOG.warn("tenant: '{}' is not empty. Unable to delete the tenant", tenantId);
throw new OMException("Tenant '" + tenantId + "' is not empty. " + "All accessIds associated to this tenant must be revoked before " + "the tenant can be deleted. See `ozone tenant user revoke`", TENANT_NOT_EMPTY);
}
// Invalidate cache entry
omMetadataManager.getTenantStateTable().addCacheEntry(new CacheKey<>(tenantId), new CacheValue<>(Optional.absent(), transactionLogIndex));
// Decrement volume refCount
if (decVolumeRefCount) {
// Check Acl
if (ozoneManager.getAclsEnabled()) {
checkAcls(ozoneManager, OzoneObj.ResourceType.VOLUME, OzoneObj.StoreType.OZONE, IAccessAuthorizer.ACLType.WRITE_ACL, volumeName, null, null);
}
omVolumeArgs = getVolumeInfo(omMetadataManager, volumeName);
// Decrement volume ref count
omVolumeArgs.decRefCount();
// Update omVolumeArgs
final String dbVolumeKey = omMetadataManager.getVolumeKey(volumeName);
omMetadataManager.getVolumeTable().addCacheEntry(new CacheKey<>(dbVolumeKey), new CacheValue<>(Optional.of(omVolumeArgs), transactionLogIndex));
// TODO: Set response dbVolumeKey?
}
// Update tenant cache
multiTenantManager.getCacheOp().deleteTenant(new OzoneTenant(tenantId));
// Compose response
//
// If decVolumeRefCount is false, return -1 to the client, otherwise
// return the actual volume refCount. Note if the actual volume refCount
// becomes negative somehow, omVolumeArgs.decRefCount() would have thrown
// earlier.
final DeleteTenantResponse.Builder deleteTenantResponse = DeleteTenantResponse.newBuilder().setVolumeName(volumeName).setVolRefCount(omVolumeArgs == null ? -1 : omVolumeArgs.getRefCount());
omClientResponse = new OMTenantDeleteResponse(omResponse.setDeleteTenantResponse(deleteTenantResponse).build(), volumeName, omVolumeArgs, tenantId);
} catch (IOException ex) {
exception = ex;
omClientResponse = new OMTenantDeleteResponse(createErrorOMResponse(omResponse, exception));
} finally {
addResponseToDoubleBuffer(transactionLogIndex, omClientResponse, ozoneManagerDoubleBufferHelper);
if (acquiredVolumeLock) {
omMetadataManager.getLock().releaseWriteLock(VOLUME_LOCK, volumeName);
}
// Release authorizer write lock
multiTenantManager.getAuthorizerLock().unlockWriteInOMRequest();
}
// Perform audit logging
auditMap.put(OzoneConsts.TENANT, tenantId);
// Audit volume ref count update
if (decVolumeRefCount) {
auditLog(ozoneManager.getAuditLogger(), buildAuditMessage(OMAction.UPDATE_VOLUME, buildVolumeAuditMap(volumeName), exception, getOmRequest().getUserInfo()));
}
// Audit tenant deletion
auditLog(ozoneManager.getAuditLogger(), buildAuditMessage(OMAction.DELETE_TENANT, auditMap, exception, getOmRequest().getUserInfo()));
if (exception == null) {
LOG.info("Deleted tenant '{}' and volume '{}'", tenantId, volumeName);
omMetrics.decNumTenants();
} else {
LOG.error("Failed to delete tenant '{}'", tenantId, exception);
omMetrics.incNumTenantDeleteFails();
}
return omClientResponse;
}
use of org.apache.hadoop.ozone.om.helpers.OmDBTenantState in project ozone by apache.
the class TestOMMultiTenantManagerImpl method setUp.
@Before
public void setUp() throws IOException {
OzoneConfiguration conf = new OzoneConfiguration();
conf.set(OZONE_OM_DB_DIRS, folder.newFolder().getAbsolutePath());
conf.set(OZONE_OM_TENANT_DEV_SKIP_RANGER, "true");
OMMetadataManager omMetadataManager = new OmMetadataManagerImpl(conf);
final String bucketNamespaceName = TENANT_ID;
final String bucketNamespacePolicyName = OMMultiTenantManager.getDefaultBucketNamespacePolicyName(TENANT_ID);
final String bucketPolicyName = OMMultiTenantManager.getDefaultBucketPolicyName(TENANT_ID);
final String userRoleName = OMMultiTenantManager.getDefaultUserRoleName(TENANT_ID);
final String adminRoleName = OMMultiTenantManager.getDefaultAdminRoleName(TENANT_ID);
final OmDBTenantState omDBTenantState = new OmDBTenantState(TENANT_ID, bucketNamespaceName, userRoleName, adminRoleName, bucketNamespacePolicyName, bucketPolicyName);
omMetadataManager.getTenantStateTable().put(TENANT_ID, omDBTenantState);
omMetadataManager.getTenantAccessIdTable().put("seed-accessId1", new OmDBAccessIdInfo(TENANT_ID, "seed-user1", false, false));
OzoneManager ozoneManager = Mockito.mock(OzoneManager.class);
Mockito.when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager);
OzoneConfiguration ozoneConfiguration = Mockito.mock(OzoneConfiguration.class);
Mockito.when(ozoneConfiguration.getTimeDuration(OZONE_OM_MULTITENANCY_RANGER_SYNC_INTERVAL, OZONE_OM_MULTITENANCY_RANGER_SYNC_INTERVAL_DEFAULT.getDuration(), OZONE_OM_MULTITENANCY_RANGER_SYNC_INTERVAL_DEFAULT.getUnit(), TimeUnit.SECONDS)).thenReturn(10L);
Mockito.when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration);
tenantManager = new OMMultiTenantManagerImpl(ozoneManager, conf);
assertEquals(1, tenantManager.getTenantCache().size());
assertEquals(1, tenantManager.getTenantCache().get(TENANT_ID).getAccessIdInfoMap().size());
}
use of org.apache.hadoop.ozone.om.helpers.OmDBTenantState in project ozone by apache.
the class OMMultiTenantManagerImpl method getTenantFromDBById.
@Override
public Tenant getTenantFromDBById(String tenantId) throws IOException {
// Policy names (not cached at the moment) have to retrieved from OM DB.
// TODO: Store policy names in cache as well if needed.
final OmDBTenantState tenantState = omMetadataManager.getTenantStateTable().get(tenantId);
if (tenantState == null) {
throw new OMException("Tenant '" + tenantId + "' does not exist", OMException.ResultCodes.TENANT_NOT_FOUND);
}
final Tenant tenantObj = new OzoneTenant(tenantState.getTenantId());
tenantObj.addTenantAccessPolicy(new RangerAccessPolicy(tenantState.getBucketNamespacePolicyName()));
tenantObj.addTenantAccessPolicy(new RangerAccessPolicy(tenantState.getBucketNamespaceName()));
tenantObj.addTenantAccessRole(tenantState.getUserRoleName());
tenantObj.addTenantAccessRole(tenantState.getAdminRoleName());
return tenantObj;
}
use of org.apache.hadoop.ozone.om.helpers.OmDBTenantState in project ozone by apache.
the class OMRangerBGSyncService method processAllPoliciesFromOMDB.
private void processAllPoliciesFromOMDB() throws IOException {
// queue or dequeue bucketNamespacePolicyName and bucketPolicyName
try (TableIterator<String, ? extends KeyValue<String, OmDBTenantState>> tenantStateTableIt = metadataManager.getTenantStateTable().iterator()) {
while (tenantStateTableIt.hasNext()) {
final KeyValue<String, OmDBTenantState> tableKeyValue = tenantStateTableIt.next();
final OmDBTenantState dbTenantState = tableKeyValue.getValue();
final String tenantId = dbTenantState.getTenantId();
final String volumeName = dbTenantState.getBucketNamespaceName();
Preconditions.checkNotNull(volumeName);
mtRangerPoliciesOpHelper(dbTenantState.getBucketNamespacePolicyName(), new PolicyInfo(tenantId, PolicyType.BUCKET_NAMESPACE_POLICY));
mtRangerPoliciesOpHelper(dbTenantState.getBucketPolicyName(), new PolicyInfo(tenantId, PolicyType.BUCKET_POLICY));
}
}
for (Map.Entry<String, PolicyInfo> entry : mtRangerPoliciesToBeCreated.entrySet()) {
final String policyName = entry.getKey();
LOG.warn("Expected policy not found in Ranger: {}", policyName);
checkLeader();
// Attempt to recreate the default volume/bucket policy if it's missing
attemptToCreateDefaultPolicy(entry.getValue());
}
for (Map.Entry<String, String> entry : mtRangerPoliciesToBeDeleted.entrySet()) {
final String policyName = entry.getKey();
LOG.info("Deleting policy from Ranger: {}", policyName);
checkLeader();
withWriteLock(() -> {
try {
authorizer.deletePolicyByName(policyName);
} catch (IOException e) {
LOG.error("Failed to delete policy: {}", policyName, e);
// Proceed to delete other policies
}
});
}
}
Aggregations