public OMClientResponse validateAndUpdateCache()

in hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/tenant/OMTenantCreateRequest.java [208:383]


  public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) {
    final long transactionLogIndex = context.getIndex();

    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 = null;
    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 boolean forceCreationWhenVolumeExists =
        request.getForceCreationWhenVolumeExists();

    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);

    Exception 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);
      }

      mergeOmLockDetails(omMetadataManager.getLock().acquireWriteLock(
          VOLUME_LOCK, volumeName));
      acquiredVolumeLock = getOmLockDetails().isLockAcquired();

      boolean skipVolumeCreation = false;
      // Check volume existence
      if (omMetadataManager.getVolumeTable().isExist(dbVolumeKey)) {
        LOG.debug("volume: '{}' already exists", volumeName);
        if (forceCreationWhenVolumeExists) {
          LOG.warn("forceCreationWhenVolumeExists = true. Resuming "
              + "tenant creation despite volume '{}' existence", volumeName);
          skipVolumeCreation = true;
        } else {
          // forceCreationWhenVolumeExists is false, throw
          throw new OMException("Volume already exists", VOLUME_ALREADY_EXISTS);
        }
      }

      mergeOmLockDetails(omMetadataManager.getLock().acquireWriteLock(
          USER_LOCK, owner));
      acquiredUserLock = getOmLockDetails().isLockAcquired();

      PersistedUserVolumeInfo volumeList = null;
      if (!skipVolumeCreation) {
        // Create volume. TODO: dedup OMVolumeCreateRequest
        omVolumeArgs = OmVolumeArgs.getFromProtobuf(volumeInfo);
        omVolumeArgs.setQuotaInBytes(OzoneConsts.QUOTA_RESET);
        omVolumeArgs.setQuotaInNamespace(OzoneConsts.QUOTA_RESET);
        omVolumeArgs.setObjectID(
            ozoneManager.getObjectIdFromTxId(transactionLogIndex));
        omVolumeArgs.setUpdateID(transactionLogIndex);

        omVolumeArgs.incRefCount();
        // Remove this check when vol ref count is also used by other features
        Preconditions.checkState(omVolumeArgs.getRefCount() == 1L,
            "refCount should have been set to 1");

        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);
      } else {
        LOG.info("Skipped volume '{}' creation. "
            + "Will only increment volume refCount", volumeName);
        omVolumeArgs = getVolumeInfo(omMetadataManager, volumeName);

        omVolumeArgs.incRefCount();
        // Remove this check when vol ref count is also used by other features
        Preconditions.checkState(omVolumeArgs.getRefCount() == 1L,
            "refCount should have been set to 1");

        omMetadataManager.getVolumeTable().addCacheEntry(
            new CacheKey<>(omMetadataManager.getVolumeKey(volumeName)),
            CacheValue.get(transactionLogIndex, omVolumeArgs));
      }

      // Audit
      auditMap = omVolumeArgs.toAuditMap();

      // 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),
          CacheValue.get(transactionLogIndex, omDBTenantState));

      // Update tenant cache
      multiTenantManager.getCacheOp().createTenant(
          tenantId, userRoleName, adminRoleName);

      omResponse.setCreateTenantResponse(
          CreateTenantResponse.newBuilder()
              .build());
      omClientResponse = new OMTenantCreateResponse(omResponse.build(),
          omVolumeArgs, volumeList, omDBTenantState);

    } catch (IOException | InvalidPathException ex) {
      exception = ex;
      omClientResponse = new OMTenantCreateResponse(
          createErrorOMResponse(omResponse, exception));
    } finally {
      if (acquiredUserLock) {
        mergeOmLockDetails(
            omMetadataManager.getLock().releaseWriteLock(USER_LOCK, owner));
      }
      if (acquiredVolumeLock) {
        mergeOmLockDetails(
            omMetadataManager.getLock().releaseWriteLock(VOLUME_LOCK,
                volumeName));
      }
      // Release authorizer write lock
      multiTenantManager.getAuthorizerLock().unlockWriteInOMRequest();
      if (omClientResponse != null) {
        omClientResponse.setOmLockDetails(getOmLockDetails());
      }
    }

    // Perform audit logging
    auditMap.put(OzoneConsts.TENANT, tenantId);
    // Note auditMap contains volume creation info
    markForAudit(ozoneManager.getAuditLogger(),
        buildAuditMessage(OMAction.CREATE_TENANT, 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;
  }