@Override
  public void process() {
    logger.info("Processing virtual pool auto tiering policy migration");

    DbClient dbClient = getDbClient();
    try {
      List<URI> virtualPoolUris = dbClient.queryByType(VirtualPool.class, true);
      Iterator<VirtualPool> virtualPools =
          dbClient.queryIterativeObjects(VirtualPool.class, virtualPoolUris, true);

      while (virtualPools.hasNext()) {
        VirtualPool virtualPool = virtualPools.next();
        // If there is a FAST policy associated with the vpool, then mark the uniquePolicyNames to
        // true
        if (virtualPool.getAutoTierPolicyName() != null
            && !virtualPool.getAutoTierPolicyName().isEmpty()) {
          // No way other than using contains to differentiate NativeGuid
          if (virtualPool.getAutoTierPolicyName().contains(NATIVE_GUID_DELIMITER)) {
            virtualPool.setUniquePolicyNames(false);
          } else {
            virtualPool.setUniquePolicyNames(true);
          }
          dbClient.persistObject(virtualPool);
          logger.info(
              "Updating VirtualPool (id={}) with  unique policy names set to {}",
              virtualPool.getId().toString(),
              virtualPool.getUniquePolicyNames());
        }
      }
    } catch (Exception ex) {
      logger.error("Exception occured while migrating auto tiering policy of vpool");
      logger.error(ex.getMessage(), ex);
    }
  }
  /**
   * get Matched Virtual Pools For Pool. This is called to calculate supported vpools during
   * unmanaged objects discovery
   *
   * @param poolUri
   * @return
   */
  public static StringSet getMatchedVirtualPoolsForPool(
      DbClient dbClient, URI poolUri, String isThinlyProvisionedUnManagedObject) {
    StringSet vpoolUriSet = new StringSet();
    // We should match all virtual pools as below:
    // 1) Virtual pools which have useMatchedPools set to true and have the storage pool in their
    // matched pools
    // 2) Virtual pools which have the storage pool in their assigned pools

    URIQueryResultList vpoolMatchedPoolsResultList = new URIQueryResultList();
    dbClient.queryByConstraint(
        ContainmentConstraint.Factory.getMatchedPoolVirtualPoolConstraint(poolUri),
        vpoolMatchedPoolsResultList);
    List<VirtualPool> vPoolsMatchedPools =
        dbClient.queryObject(VirtualPool.class, vpoolMatchedPoolsResultList);
    String provisioningTypeUnManagedObject =
        UnManagedVolume.SupportedProvisioningType.getProvisioningType(
            isThinlyProvisionedUnManagedObject);
    StoragePool storagePool = dbClient.queryObject(StoragePool.class, poolUri);
    for (VirtualPool vPool : vPoolsMatchedPools) {
      if (!VirtualPool.vPoolSpecifiesHighAvailability(vPool)) {
        List<StoragePool> validPools = VirtualPool.getValidStoragePools(vPool, dbClient, true);
        for (StoragePool sPool : validPools) {
          if (sPool.getId().equals(storagePool.getId())
              && provisioningTypeUnManagedObject.equalsIgnoreCase(
                  vPool.getSupportedProvisioningType())) {
            vpoolUriSet.add(vPool.getId().toString());
            break;
          }
        }
      }
    }

    return vpoolUriSet;
  }
  // Getting all the vpools
  public static StringSet getMatchedVirtualPoolsForPool(DbClient dbClient, URI poolUri) {
    StringSet vpoolUriSet = new StringSet();
    // We should match all virtual pools as below:
    // 1) Virtual pools which have useMatchedPools set to true and have the storage pool in their
    // matched pools
    // 2) Virtual pools which have the storage pool in their assigned pools

    URIQueryResultList vpoolMatchedPoolsResultList = new URIQueryResultList();
    dbClient.queryByConstraint(
        ContainmentConstraint.Factory.getMatchedPoolVirtualPoolConstraint(poolUri),
        vpoolMatchedPoolsResultList);
    List<VirtualPool> vPoolsMatchedPools =
        dbClient.queryObject(VirtualPool.class, vpoolMatchedPoolsResultList);
    StoragePool storagePool = dbClient.queryObject(StoragePool.class, poolUri);
    for (VirtualPool vPool : vPoolsMatchedPools) {
      List<StoragePool> validPools = VirtualPool.getValidStoragePools(vPool, dbClient, true);
      for (StoragePool sPool : validPools) {
        if (sPool.getId().equals(storagePool.getId())) {
          vpoolUriSet.add(vPool.getId().toString());
          break;
        }
      }
    }

    return vpoolUriSet;
  }
  /**
   * Update a quota
   *
   * @prereq none
   * @param tenant_id the URN of the tenant
   * @param target_tenant_id the URN of the target tenant for which quota is being modified
   * @brief Update Quota
   * @return Quota details of target_tenant_id
   */
  @PUT
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Path("/{target_tenant_id}")
  @CheckPermission(
      roles = {Role.SYSTEM_MONITOR, Role.TENANT_ADMIN},
      acls = {ACL.ANY})
  public Response updateQuota(
      @PathParam("tenant_id") String openstack_tenant_id,
      @PathParam("target_tenant_id") String openstack_target_tenant_id,
      CinderQuotaDetails quotaUpdates,
      @Context HttpHeaders header) {

    _log.info("Updating Quota");
    Project project =
        getCinderHelper().getProject(openstack_target_tenant_id.toString(), getUserFromContext());
    if (project == null) {
      throw APIException.badRequests.projectWithTagNonexistent(openstack_target_tenant_id);
    }

    long maxQuota = 0L;
    if (project.getQuotaEnabled()) {
      maxQuota = (long) (project.getQuota().intValue());
    } else {
      maxQuota = DEFAULT_PROJECT_TOTALGB_QUOTA;
    }

    // bVpoolQuotaUpdate will be set to true if the user is updating the quota of a vpool w.r.t a
    // project
    // bVpoolQuotaUpdate will be set to false if the user is updating the quota of the project
    boolean bVpoolQuotaUpdate = isVpoolQuotaUpdate(quotaUpdates.quota_set);
    String vpoolName = null;
    VirtualPool objVpool = null;

    if (bVpoolQuotaUpdate) {
      vpoolName = getVpoolName(quotaUpdates.quota_set);
      _log.info("Vpool for which quota is being updated is {}", vpoolName);
      objVpool = getCinderHelper().getVpool(vpoolName);

      if (objVpool == null) {
        _log.info("vpool with the given name doesnt exist");
        throw APIException.badRequests.parameterIsNotValid(vpoolName);
      }
      _log.info("objVpool.getLabel() is {}", objVpool.getLabel());
    }

    List<URI> quotas = _dbClient.queryByType(QuotaOfCinder.class, true);
    boolean noEntriesInDB = true;
    for (URI quota : quotas) {
      QuotaOfCinder quotaObj = _dbClient.queryObject(QuotaOfCinder.class, quota);
      if ((quotaObj.getProject() != null)
          && (quotaObj.getProject().toString().equalsIgnoreCase(project.getId().toString()))) {
        _log.info("QuotaObj being updated is {}", quotaObj.toString());

        URI vpoolUri = quotaObj.getVpool();

        if ((!bVpoolQuotaUpdate) && (vpoolUri != null)) {
          // The user requested update of project quota.
          // But the current db entry quota for vpool w.r.t project.
          // Hence just skip the db entry as this is not our concern.
          continue;
        }

        if ((bVpoolQuotaUpdate) && (vpoolUri != null)) {
          // The user requested quota update for a vpool w.r.t a project.
          // The current db entry that we looking into has vpool entry.
          // Hence we should further check if the vpool value is same as the vpool for which the
          // user wants to set quota
          VirtualPool pool = _dbClient.queryObject(VirtualPool.class, vpoolUri);
          if ((pool != null)
              && (pool.getLabel().equals(vpoolName))
              && (vpoolName != null)
              && (vpoolName.length() > 0)) {

            if (quotaUpdates.quota_set.containsKey("gigabytes_" + vpoolName))
              quotaObj.setTotalQuota(
                  new Long(quotaUpdates.quota_set.get("gigabytes_" + vpoolName)));
            if (quotaUpdates.quota_set.containsKey("volumes_" + vpoolName))
              quotaObj.setVolumesLimit(
                  new Long(quotaUpdates.quota_set.get("volumes_" + vpoolName)));
            if (quotaUpdates.quota_set.containsKey("snapshots_" + vpoolName))
              quotaObj.setSnapshotsLimit(
                  new Long(quotaUpdates.quota_set.get("snapshots_" + vpoolName)));
            noEntriesInDB = false;
            _dbClient.updateObject(quotaObj);
            return getQuotaDetailFormat(header, quotaUpdates);
          }
        } else if (!bVpoolQuotaUpdate) {
          // The user requested update of project quota.
          // The current db entry is a project quota entity.(because to reach here vpoolUri should
          // be Null.
          if (quotaUpdates.quota_set.containsKey("gigabytes"))
            quotaObj.setTotalQuota(new Long(quotaUpdates.quota_set.get("gigabytes")));
          if (quotaUpdates.quota_set.containsKey("volumes"))
            quotaObj.setVolumesLimit(new Long(quotaUpdates.quota_set.get("volumes")));
          if (quotaUpdates.quota_set.containsKey("snapshots"))
            quotaObj.setSnapshotsLimit(new Long(quotaUpdates.quota_set.get("snapshots")));
          noEntriesInDB = false;
          _dbClient.updateObject(quotaObj);
          return getQuotaDetailFormat(header, quotaUpdates);
        }
      }
    }

    if (noEntriesInDB) {
      _log.info("No entries in the QuotaOfCinder column family");
      QuotaOfCinder objQuotaOfCinder = new QuotaOfCinder();
      objQuotaOfCinder.setProject(project.getId());

      if (bVpoolQuotaUpdate) {
        objQuotaOfCinder.setVpool(objVpool.getId());
        _log.info("Updating Quota of Vpool");
        if (quotaUpdates.quota_set.containsKey("gigabytes_" + vpoolName))
          objQuotaOfCinder.setTotalQuota(
              new Long(quotaUpdates.quota_set.get("gigabytes_" + vpoolName)));
        else objQuotaOfCinder.setTotalQuota(DEFAULT_VOLUME_TYPE_TOTALGB_QUOTA);

        if (quotaUpdates.quota_set.containsKey("volumes_" + vpoolName))
          objQuotaOfCinder.setVolumesLimit(
              new Long(quotaUpdates.quota_set.get("volumes_" + vpoolName)));
        else objQuotaOfCinder.setVolumesLimit(DEFAULT_VOLUME_TYPE_VOLUMES_QUOTA);

        if (quotaUpdates.quota_set.containsKey("snapshots_" + vpoolName))
          objQuotaOfCinder.setSnapshotsLimit(
              new Long(quotaUpdates.quota_set.get("snapshots_" + vpoolName)));
        else objQuotaOfCinder.setSnapshotsLimit(DEFAULT_VOLUME_TYPE_SNAPSHOTS_QUOTA);

      } else {
        if (quotaUpdates.quota_set.containsKey("gigabytes"))
          objQuotaOfCinder.setTotalQuota(new Long(quotaUpdates.quota_set.get("gigabytes")));
        else objQuotaOfCinder.setTotalQuota(maxQuota);

        if (quotaUpdates.quota_set.containsKey("volumes"))
          objQuotaOfCinder.setVolumesLimit(new Long(quotaUpdates.quota_set.get("volumes")));
        else objQuotaOfCinder.setVolumesLimit(DEFAULT_PROJECT_VOLUMES_QUOTA);

        if (quotaUpdates.quota_set.containsKey("snapshots"))
          objQuotaOfCinder.setSnapshotsLimit(new Long(quotaUpdates.quota_set.get("snapshots")));
        else objQuotaOfCinder.setSnapshotsLimit(DEFAULT_PROJECT_SNAPSHOTS_QUOTA);
      }
      objQuotaOfCinder.setId(URI.create(UUID.randomUUID().toString()));
      _dbClient.createObject(objQuotaOfCinder);
      return getQuotaDetailFormat(header, quotaUpdates);
    }
    return getQuotaDetailFormat(header, quotaUpdates);
  }
  private TaskResourceRep initiateBucketCreation(
      BucketParam param, Project project, TenantOrg tenant, DataObject.Flag[] flags)
      throws InternalException {
    ArgValidator.checkFieldUriType(param.getVpool(), VirtualPool.class, "vpool");
    ArgValidator.checkFieldUriType(param.getVarray(), VirtualArray.class, "varray");

    Long softQuota = SizeUtil.translateSize(param.getSoftQuota());
    Long hardQuota = SizeUtil.translateSize(param.getHardQuota());
    Integer retention = Integer.valueOf(param.getRetention());

    // Hard Quota should be more than SoftQuota
    verifyQuotaValues(softQuota, hardQuota, param.getLabel());

    // check varray
    VirtualArray neighborhood = _dbClient.queryObject(VirtualArray.class, param.getVarray());
    ArgValidator.checkEntity(neighborhood, param.getVarray(), false);
    _permissionsHelper.checkTenantHasAccessToVirtualArray(tenant.getId(), neighborhood);

    // check vpool reference
    VirtualPool cos = _dbClient.queryObject(VirtualPool.class, param.getVpool());
    _permissionsHelper.checkTenantHasAccessToVirtualPool(tenant.getId(), cos);
    ArgValidator.checkEntity(cos, param.getVpool(), false);
    if (!VirtualPool.Type.object.name().equals(cos.getType())) {
      throw APIException.badRequests.virtualPoolNotForObjectStorage(VirtualPool.Type.object.name());
    }

    // verify retention. Its validated only if Retention is configured.
    if (retention != 0 && cos.getMaxRetention() != 0 && retention > cos.getMaxRetention()) {
      throw APIException.badRequests.insufficientRetentionForVirtualPool(cos.getLabel(), "bucket");
    }

    VirtualPoolCapabilityValuesWrapper capabilities = new VirtualPoolCapabilityValuesWrapper();

    capabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, Integer.valueOf(1));
    capabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, Boolean.FALSE);

    List<BucketRecommendation> placement =
        _bucketScheduler.placeBucket(neighborhood, cos, capabilities);
    if (placement.isEmpty()) {
      throw APIException.badRequests.noMatchingStoragePoolsForVpoolAndVarray(
          cos.getId(), neighborhood.getId());
    }

    // Randomly select a recommended pool
    Collections.shuffle(placement);
    BucketRecommendation recommendation = placement.get(0);

    String task = UUID.randomUUID().toString();
    Bucket bucket = prepareBucket(param, project, tenant, neighborhood, cos, flags, recommendation);

    _log.info(
        String.format(
            "createBucket --- Bucket: %1$s, StoragePool: %2$s, StorageSystem: %3$s",
            bucket.getId(),
            recommendation.getSourceStoragePool(),
            recommendation.getSourceStorageSystem()));

    Operation op =
        _dbClient.createTaskOpStatus(
            Bucket.class, bucket.getId(), task, ResourceOperationTypeEnum.CREATE_BUCKET);
    op.setDescription("Bucket Create");

    // Controller invocation
    StorageSystem system =
        _dbClient.queryObject(StorageSystem.class, recommendation.getSourceStorageSystem());
    ObjectController controller = getController(ObjectController.class, system.getSystemType());
    controller.createBucket(
        recommendation.getSourceStorageSystem(),
        recommendation.getSourceStoragePool(),
        bucket.getId(),
        bucket.getName(),
        bucket.getNamespace(),
        bucket.getRetention(),
        bucket.getHardQuota(),
        bucket.getSoftQuota(),
        bucket.getOwner(),
        task);

    auditOp(
        OperationTypeEnum.CREATE_BUCKET,
        true,
        AuditLogManager.AUDITOP_BEGIN,
        param.getLabel(),
        param.getHardQuota(),
        neighborhood.getId().toString(),
        project == null ? null : project.getId().toString());

    return toTask(bucket, task, op);
  }
  /**
   * Filter vpools from the qualified list. rpSource true: Filter out anything other than RP source
   * vpools rpSource false: Filter out RP and SRDF source vpools
   *
   * @param dbClient dbclient
   * @param unManagedVolume unmanaged volume
   * @param personality SOURCE, TARGET, or METADATA
   */
  private void filterProtectedVpools(
      DbClient dbClient, UnManagedVolume unManagedVolume, String personality) {

    if (unManagedVolume.getSupportedVpoolUris() != null
        && !unManagedVolume.getSupportedVpoolUris().isEmpty()) {
      Iterator<VirtualPool> vpoolItr =
          dbClient.queryIterativeObjects(
              VirtualPool.class, URIUtil.toURIList(unManagedVolume.getSupportedVpoolUris()));
      while (vpoolItr.hasNext()) {
        boolean remove = false;
        VirtualPool vpool = vpoolItr.next();

        // If this is an SRDF source vpool, we can filter out since we're dealing with an RP volume
        if (vpool.getProtectionRemoteCopySettings() != null) {
          remove = true;
        }

        // If this is not an RP source, the vpool should be filtered out if:
        // The vpool is an RP vpool (has settings) and target vpools are non-null
        if (vpool.getProtectionVarraySettings() != null
            && ((Volume.PersonalityTypes.TARGET.name().equalsIgnoreCase(personality))
                || Volume.PersonalityTypes.METADATA.name().equalsIgnoreCase(personality))) {
          boolean foundEmptyTargetVpool = false;
          Map<URI, VpoolProtectionVarraySettings> settings =
              VirtualPool.getProtectionSettings(vpool, dbClient);
          for (Map.Entry<URI, VpoolProtectionVarraySettings> setting : settings.entrySet()) {
            if (NullColumnValueGetter.isNullURI(setting.getValue().getVirtualPool())) {
              foundEmptyTargetVpool = true;
              break;
            }
          }

          // If this is a journal volume, also check the journal vpools. If they're not set, we
          // cannot filter out this vpool.
          if (Volume.PersonalityTypes.METADATA.name().equalsIgnoreCase(personality)
              && (NullColumnValueGetter.isNullValue(vpool.getJournalVpool())
                  || NullColumnValueGetter.isNullValue(vpool.getStandbyJournalVpool()))) {
            foundEmptyTargetVpool = true;
          }

          // If every relevant target (and journal for journal volumes) vpool is filled-in, then
          // you would never assign your target volume to this source vpool, so filter it out.
          if (!foundEmptyTargetVpool) {
            remove = true;
          }
        }

        if (Volume.PersonalityTypes.SOURCE.name().equalsIgnoreCase(personality)) {
          if (!VirtualPool.vPoolSpecifiesProtection(vpool)) {
            // If this an RP source, the vpool must be an RP vpool
            remove = true;
          } else if (unManagedVolume
                  .getVolumeInformation()
                  .containsKey(SupportedVolumeInformation.RP_STANDBY_INTERNAL_SITENAME.toString())
              && !VirtualPool.vPoolSpecifiesMetroPoint(vpool)) {
            // Since this is a Source volume with the presence of RP_STANDBY_INTERNAL_SITENAME
            // it indicates that this volume is MetroPoint, if we get here, this is vpool
            // must be filtered out since it's not MP.
            remove = true;
          }
        }

        if (remove) {
          log.info(
              "Removing virtual pool "
                  + vpool.getLabel()
                  + " from supported vpools for unmanaged volume: "
                  + unManagedVolume.getLabel());
          unManagedVolume.getSupportedVpoolUris().remove(vpool.getId().toString());
        }
      }
    }
  }
  /**
   * Release a file system from its current tenant & project for internal object usage
   *
   * @param id the URN of a ViPR file system to be released
   * @return the updated file system
   * @throws InternalException
   */
  @POST
  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
  @Path("/{id}/release")
  public FileShareRestRep releaseFileSystemInternal(@PathParam("id") URI id)
      throws InternalException {

    ArgValidator.checkFieldUriType(id, FileShare.class, "id");
    FileShare fs = _fileService.queryResource(id);

    // if the FS is already marked as internal, we can skip all this logic
    // and just return success down at the bottom
    if (!fs.checkInternalFlags(Flag.INTERNAL_OBJECT)) {
      URI tenantURI = fs.getTenant().getURI();
      if (!_permissionsHelper.userHasGivenRole(
          getUserFromContext(), tenantURI, Role.TENANT_ADMIN)) {
        throw APIException.forbidden.onlyAdminsCanReleaseFileSystems(Role.TENANT_ADMIN.toString());
      }

      // we can't release a fs that has exports
      FSExportMap exports = fs.getFsExports();
      if ((exports != null) && (!exports.isEmpty())) {
        throw APIException.badRequests.cannotReleaseFileSystemExportExists(
            exports.keySet().toString());
      }

      // we can't release a fs that has shares
      SMBShareMap shares = fs.getSMBFileShares();
      if ((shares != null) && (!shares.isEmpty())) {
        throw APIException.badRequests.cannotReleaseFileSystemSharesExists(
            shares.keySet().toString());
      }

      // files systems with pending operations can't be released
      if (fs.getOpStatus() != null) {
        for (String opId : fs.getOpStatus().keySet()) {
          Operation op = fs.getOpStatus().get(opId);
          if (Operation.Status.pending.name().equals(op.getStatus())) {
            throw APIException.badRequests.cannotReleaseFileSystemWithTasksPending();
          }
        }
      }

      // file systems with snapshots can't be released
      Integer snapCount = _fileService.getNumSnapshots(fs);
      if (snapCount > 0) {
        throw APIException.badRequests.cannotReleaseFileSystemSnapshotExists(snapCount);
      }

      TenantOrg rootTenant = _permissionsHelper.getRootTenant();

      // we can't release the file system to the root tenant if the root tenant has no access
      // to the filesystem's virtual pool
      ArgValidator.checkFieldNotNull(fs.getVirtualPool(), "virtualPool");
      VirtualPool virtualPool =
          _permissionsHelper.getObjectById(fs.getVirtualPool(), VirtualPool.class);
      ArgValidator.checkEntity(virtualPool, fs.getVirtualPool(), false);
      if (!_permissionsHelper.tenantHasUsageACL(rootTenant.getId(), virtualPool)) {
        throw APIException.badRequests.cannotReleaseFileSystemRootTenantLacksVPoolACL(
            virtualPool.getId().toString());
      }

      fs.setOriginalProject(fs.getProject().getURI());
      fs.setTenant(new NamedURI(rootTenant.getId(), fs.getLabel()));
      fs.setProject(new NamedURI(_internalProject.getId(), fs.getLabel()));
      fs.addInternalFlags(INTERNAL_FILESHARE_FLAGS);
      _dbClient.updateAndReindexObject(fs);

      // audit against the source project, not the new dummy internal project
      auditOp(
          OperationTypeEnum.RELEASE_FILE_SYSTEM,
          true,
          null,
          fs.getId().toString(),
          fs.getOriginalProject().toString());
    }

    return map(fs);
  }