/** * 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; }
/** * Validate the Target Volume VirtualArray with the Source Volume VPool VirtualArray. * * @param type * @param unManagedVolume * @param virtualArray */ private void validateTargetVolumeVpoolWithSourceVolume( UnManagedVolume unManagedVolume, VirtualArray virtualArray) { String sourceUnManagedVolumeId = PropertySetterUtil.extractValueFromStringSet( SupportedVolumeInformation.REMOTE_MIRROR_SOURCE_VOLUME.toString(), unManagedVolume.getVolumeInformation()); String sourceVolumeId = sourceUnManagedVolumeId.replace( VolumeIngestionUtil.UNMANAGEDVOLUME, VolumeIngestionUtil.VOLUME); List<URI> sourceUris = _dbClient.queryByConstraint( AlternateIdConstraint.Factory.getVolumeNativeGuidConstraint(sourceVolumeId)); if (sourceUris.isEmpty()) { _logger.info( "Source {} Not found for target {}", sourceVolumeId, unManagedVolume.getNativeGuid()); } else { // if source volume is ingested, then Volume sourceVolume = _dbClient.queryObject(Volume.class, sourceUris.get(0)); // check whether the source Volume's VPool is actually having this // target Volume's varray // specified as remote VirtualPool sourceVPool = _dbClient.queryObject(VirtualPool.class, sourceVolume.getVirtualPool()); Map<URI, VpoolRemoteCopyProtectionSettings> settings = sourceVPool.getRemoteProtectionSettings(sourceVPool, _dbClient); if (null == settings || settings.isEmpty() || !settings.containsKey(virtualArray.getId())) { _logger.info( "Target Volume's VArray {} is not matching already ingested source volume virtual pool's remote VArray ", virtualArray.getId()); throw IngestionException.exceptions.unmanagedSRDFTargetVolumeVArrayMismatch( unManagedVolume.getLabel(), sourceVolume.getVirtualArray().toString()); } } }
// 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; }
/** * Checks the UnManaged Volume's policy with vPool's policy. * * @param vPool the vPool * @param autoTierPolicyId the auto tier policy id on unmanaged volume * @param system the system * @return true, if matching, false otherwise */ public static boolean checkVPoolValidForUnManagedVolumeAutoTieringPolicy( VirtualPool vPool, String autoTierPolicyId, StorageSystem system) { _log.debug("Policy Id: {}, vPool: {}", autoTierPolicyId, vPool); boolean policyMatching = false; String policyIdfromVPool = vPool.getAutoTierPolicyName(); if (autoTierPolicyId != null) { if (policyIdfromVPool != null) { if (vPool.getUniquePolicyNames() || DiscoveredDataObject.Type.vnxblock.name().equalsIgnoreCase(system.getSystemType())) { // Unique Policy names field will not be set for VNX. vPool will have policy name, not the // policy's nativeGuid policyIdfromVPool = NativeGUIDGenerator.generateAutoTierPolicyNativeGuid( system.getNativeGuid(), policyIdfromVPool, NativeGUIDGenerator.getTieringPolicyKeyForSystem(system)); _log.debug("Policy Id generated: {}", policyIdfromVPool); } if (autoTierPolicyId.equalsIgnoreCase(policyIdfromVPool)) { policyMatching = true; } } } else if ((policyIdfromVPool == null) || (policyIdfromVPool.equalsIgnoreCase("none"))) { // if policy is not set in both unmanaged volume and vPool. Note // that the value in the vpool could be set to "none". policyMatching = true; } // Default policy for VNX - match volume with default policy to vPool with no policy as well if (!policyMatching && DiscoveredDataObject.Type.vnxblock.name().equalsIgnoreCase(system.getSystemType())) { if (autoTierPolicyId != null && autoTierPolicyId.contains(VnxFastPolicy.DEFAULT_START_HIGH_THEN_AUTOTIER.name()) && policyIdfromVPool == null) { policyMatching = true; } } // Default policy for HDS - match volume with default policy to vPool with no policy as well if (!policyMatching && DiscoveredDataObject.Type.hds.name().equalsIgnoreCase(system.getSystemType())) { if (autoTierPolicyId != null && autoTierPolicyId.contains(HitachiTieringPolicy.All.name()) && policyIdfromVPool == null) { policyMatching = true; } } return policyMatching; }
@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); } }
/** * Validate the SourceVolume VArray details with ingested target volumes VArray. * * @param unManagedVolume * @param VirtualPool * @return */ private void validateSourceVolumeVarrayWithTargetVPool( UnManagedVolume unManagedVolume, VirtualPool sourceVPool) { StringSetMap unManagedVolumeInformation = unManagedVolume.getVolumeInformation(); // find whether all targets are ingested StringSet targetUnManagedVolumeGuids = unManagedVolumeInformation.get(SupportedVolumeInformation.REMOTE_MIRRORS.toString()); if (null != targetUnManagedVolumeGuids && !targetUnManagedVolumeGuids.isEmpty()) { StringSet targetVolumeNativeGuids = VolumeIngestionUtil.getListofVolumeIds(targetUnManagedVolumeGuids); // check whether target exists List<URI> targetUris = VolumeIngestionUtil.getVolumeUris(targetVolumeNativeGuids, _dbClient); if (null == targetUris || targetUris.isEmpty()) { _logger.info( "None of the targets ingested for source volume: {}", unManagedVolume.getNativeGuid()); } else { List<Volume> targetVolumes = _dbClient.queryObject(Volume.class, targetUris); for (Volume targetVolume : targetVolumes) { Map<URI, VpoolRemoteCopyProtectionSettings> settings = sourceVPool.getRemoteProtectionSettings(sourceVPool, _dbClient); if (null == settings || settings.size() == 0 || !settings.containsKey(targetVolume.getVirtualArray())) { _logger.info( "Target Volume's VArray {} is not matching already ingested source volume virtual pool's remote VArray {}", targetVolume.getVirtualArray(), Joiner.on(",").join(settings.keySet())); throw IngestionException.exceptions.unmanagedSRDFSourceVolumeVArrayMismatch( unManagedVolume.getLabel(), targetVolume.getVirtualArray().toString()); } } } } }
/** * Allocate, initialize and persist state of the Bucket being created. * * @param param * @param project * @param tenantOrg * @param neighborhood * @param vpool * @param flags * @param placement * @return */ private Bucket prepareBucket( BucketParam param, Project project, TenantOrg tenantOrg, VirtualArray neighborhood, VirtualPool vpool, DataObject.Flag[] flags, BucketRecommendation placement) { _log.debug("Preparing Bucket creation for Param : {}", param); StoragePool pool = null; Bucket bucket = new Bucket(); bucket.setId(URIUtil.createId(Bucket.class)); bucket.setLabel(param.getLabel().replaceAll(SPECIAL_CHAR_REGEX, "")); bucket.setHardQuota(SizeUtil.translateSize(param.getHardQuota())); bucket.setSoftQuota(SizeUtil.translateSize(param.getSoftQuota())); bucket.setRetention(Integer.valueOf(param.getRetention())); bucket.setOwner(getOwner(param.getOwner())); bucket.setNamespace(tenantOrg.getNamespace()); bucket.setVirtualPool(param.getVpool()); if (project != null) { bucket.setProject(new NamedURI(project.getId(), bucket.getLabel())); } bucket.setTenant(new NamedURI(tenantOrg.getId(), param.getLabel())); bucket.setVirtualArray(neighborhood.getId()); if (null != placement.getSourceStoragePool()) { pool = _dbClient.queryObject(StoragePool.class, placement.getSourceStoragePool()); if (null != pool) { bucket.setProtocol(new StringSet()); bucket .getProtocol() .addAll( VirtualPoolUtil.getMatchingProtocols(vpool.getProtocols(), pool.getProtocols())); } } bucket.setStorageDevice(placement.getSourceStorageSystem()); bucket.setPool(placement.getSourceStoragePool()); bucket.setOpStatus(new OpStatusMap()); // Bucket name to be used at Storage System String bucketName = project.getLabel() + UNDER_SCORE + param.getLabel(); bucket.setName(bucketName.replaceAll(SPECIAL_CHAR_REGEX, "")); // Update Bucket path StringBuilder bucketPath = new StringBuilder(); bucketPath .append(tenantOrg.getNamespace()) .append(SLASH) .append(project.getLabel()) .append(SLASH) .append(param.getLabel()); bucket.setPath(bucketPath.toString()); if (flags != null) { bucket.addInternalFlags(flags); } _dbClient.createObject(bucket); return bucket; }
@Override protected void setProtocol(StoragePool pool, Volume volume, VirtualPool vPool) { if (null == volume.getProtocol()) { volume.setProtocol(new StringSet()); } volume.getProtocol().addAll(vPool.getProtocols()); }
/** * Filters supported vPools in UnManaged Volume based on Auto-Tiering Policy. * * @param unManagedVolume the UnManaged volume * @param policyName the policy name associated with UnManaged volume * @param system the system * @param dbClient the db client */ public static void filterSupportedVpoolsBasedOnTieringPolicy( UnManagedVolume unManagedVolume, String policyName, StorageSystem system, DbClient dbClient) { StringSetMap unManagedVolumeInformation = unManagedVolume.getVolumeInformation(); StringSet supportedVpoolURIs = unManagedVolumeInformation.get(SupportedVolumeInformation.SUPPORTED_VPOOL_LIST.toString()); List<String> vPoolsToRemove = new ArrayList<String>(); if (supportedVpoolURIs != null) { Iterator<String> itr = supportedVpoolURIs.iterator(); while (itr.hasNext()) { String uri = itr.next(); VirtualPool vPool = dbClient.queryObject(VirtualPool.class, URI.create(uri)); if (vPool != null && !vPool.getInactive()) { // generate unmanaged volume's policyId String autoTierPolicyId = NativeGUIDGenerator.generateAutoTierPolicyNativeGuid( system.getNativeGuid(), policyName, NativeGUIDGenerator.getTieringPolicyKeyForSystem(system)); if (!checkVPoolValidForUnManagedVolumeAutoTieringPolicy( vPool, autoTierPolicyId, system)) { String msg = "Removing vPool %s from SUPPORTED_VPOOL_LIST in UnManagedVolume %s " + "since Auto-tiering Policy %s in UnManaged Volume does not match with vPool's (%s)"; _log.info( String.format( msg, new Object[] { uri, unManagedVolume.getId(), autoTierPolicyId, vPool.getAutoTierPolicyName() })); vPoolsToRemove.add(uri); } } else { // remove Inactive vPool URI vPoolsToRemove.add(uri); } } } for (String uri : vPoolsToRemove) { // UnManagedVolume object is persisted by caller supportedVpoolURIs.remove(uri); } }
/** * Get the summary list of all Quotas for the given tenant * * @prereq none * @param tenant_id the URN of the tenant asking for quotas * @param target_tenant_id * @brief Get the summary list of all Quotas * @return Quota details of target_tenant_id */ @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("/{target_tenant_id}") @CheckPermission( roles = {Role.SYSTEM_MONITOR, Role.TENANT_ADMIN}, acls = {ACL.ANY}) public Response getQuotaDetails( @PathParam("target_tenant_id") String openstack_target_tenant_id, @Context HttpHeaders header) { Project project = getCinderHelper().getProject(openstack_target_tenant_id.toString(), getUserFromContext()); if (project == null) { throw APIException.badRequests.projectWithTagNonexistent(openstack_target_tenant_id); } long maxQuota = 0; if (project.getQuotaEnabled()) { maxQuota = (long) (project.getQuota().intValue()); } else { maxQuota = DEFAULT_PROJECT_TOTALGB_QUOTA; } List<URI> quotas = _dbClient.queryByType(QuotaOfCinder.class, true); Map<String, String> vpoolsMap = new HashMap<String, String>(); boolean bDefProjQuotasExist = false; CinderQuotaDetails respCinderQuota = new CinderQuotaDetails(); for (URI quota : quotas) { QuotaOfCinder quotaObj = _dbClient.queryObject(QuotaOfCinder.class, quota); if ((quotaObj.getProject() != null) && (quotaObj.getProject().toString().equalsIgnoreCase(project.getId().toString()))) { if (quotaObj.getVpool() != null) { VirtualPool pool = _dbClient.queryObject(VirtualPool.class, quotaObj.getVpool()); respCinderQuota.quota_set.put( "gigabytes" + "_" + pool.getLabel(), String.valueOf(quotaObj.getTotalQuota())); respCinderQuota.quota_set.put( "snapshots" + "_" + pool.getLabel(), String.valueOf(quotaObj.getSnapshotsLimit())); respCinderQuota.quota_set.put( "volumes" + "_" + pool.getLabel(), String.valueOf(quotaObj.getVolumesLimit())); vpoolsMap.put(pool.getLabel(), pool.getLabel()); } else { respCinderQuota.quota_set.put("gigabytes", String.valueOf(quotaObj.getTotalQuota())); respCinderQuota.quota_set.put("snapshots", String.valueOf(quotaObj.getSnapshotsLimit())); respCinderQuota.quota_set.put( "volumes", String.valueOf(quotaObj.getVolumesLimit().intValue())); bDefProjQuotasExist = true; } } } if (!bDefProjQuotasExist) { respCinderQuota.quota_set.put("gigabytes", String.valueOf(maxQuota)); respCinderQuota.quota_set.put("snapshots", String.valueOf(DEFAULT_PROJECT_SNAPSHOTS_QUOTA)); respCinderQuota.quota_set.put("volumes", String.valueOf(DEFAULT_PROJECT_VOLUMES_QUOTA)); getCinderHelper().createProjectDefaultQuota(project); } StorageOSUser user = getUserFromContext(); URI tenantId = URI.create(user.getTenantId()); List<URI> vpools = _dbClient.queryByType(VirtualPool.class, true); for (URI vpool : vpools) { VirtualPool pool = _dbClient.queryObject(VirtualPool.class, vpool); _log.debug("Looking up vpool {}", pool.getLabel()); if (pool != null && pool.getType().equalsIgnoreCase(VirtualPool.Type.block.name())) { if (_permissionsHelper.tenantHasUsageACL(tenantId, pool)) { if (vpoolsMap.containsKey(pool.getLabel())) { continue; } else { respCinderQuota.quota_set.put( "gigabytes" + "_" + pool.getLabel(), String.valueOf(DEFAULT_VOLUME_TYPE_TOTALGB_QUOTA)); respCinderQuota.quota_set.put( "snapshots" + "_" + pool.getLabel(), String.valueOf(DEFAULT_VOLUME_TYPE_SNAPSHOTS_QUOTA)); respCinderQuota.quota_set.put( "volumes" + "_" + pool.getLabel(), String.valueOf(DEFAULT_VOLUME_TYPE_VOLUMES_QUOTA)); getCinderHelper().createVpoolDefaultQuota(project, pool); } } } } return getQuotaDetailFormat(header, respCinderQuota); }
/** * Places and prepares the HA volumes when copying a distributed VPLEX volume. * * @param name The base name for the volume. * @param copyCount The number of copies to be made. * @param size The size for the HA volume. * @param vplexSystem A reference to the VPLEX storage system. * @param vplexSystemProject A reference to the VPLEX system project. * @param srcVarray The virtual array for the VPLEX volume being copied. * @param srcHAVolume The HA volume of the VPLEX volume being copied. * @param taskId The task identifier. * @param volumeDescriptors The list of descriptors. * @return A list of the prepared HA volumes for the VPLEX volume copy. */ private List<Volume> prepareFullCopyHAVolumes( String name, int copyCount, Long size, StorageSystem vplexSystem, Project vplexSystemProject, VirtualArray srcVarray, Volume srcHAVolume, String taskId, List<VolumeDescriptor> volumeDescriptors) { List<Volume> copyHAVolumes = new ArrayList<Volume>(); // Get the storage placement recommendations for the volumes. // Placement must occur on the same VPLEX system Set<URI> vplexSystemURIS = new HashSet<URI>(); vplexSystemURIS.add(vplexSystem.getId()); VirtualArray haVarray = _dbClient.queryObject(VirtualArray.class, srcHAVolume.getVirtualArray()); VirtualPool haVpool = _dbClient.queryObject(VirtualPool.class, srcHAVolume.getVirtualPool()); VirtualPoolCapabilityValuesWrapper haCapabilities = new VirtualPoolCapabilityValuesWrapper(); haCapabilities.put(VirtualPoolCapabilityValuesWrapper.SIZE, size); haCapabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, copyCount); VirtualPool vpool = BlockFullCopyUtils.queryFullCopySourceVPool(srcHAVolume, _dbClient); if (VirtualPool.ProvisioningType.Thin.toString() .equalsIgnoreCase(vpool.getSupportedProvisioningType())) { haCapabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, Boolean.TRUE); // To guarantee that storage pool for a copy has enough physical // space to contain current allocated capacity of thin source volume haCapabilities.put( VirtualPoolCapabilityValuesWrapper.THIN_VOLUME_PRE_ALLOCATE_SIZE, BlockFullCopyUtils.getAllocatedCapacityForFullCopySource(srcHAVolume, _dbClient)); } List<Recommendation> recommendations = ((VPlexScheduler) _scheduler) .scheduleStorageForImport( srcVarray, vplexSystemURIS, haVarray, haVpool, haCapabilities); if (recommendations.isEmpty()) { throw APIException.badRequests.noStorageForHaVolumesForVplexVolumeCopies(); } // Prepare the HA volumes for the VPLEX volume copy. int copyIndex = 1; for (Recommendation recommendation : recommendations) { VPlexRecommendation haRecommendation = (VPlexRecommendation) recommendation; for (int i = 0; i < haRecommendation.getResourceCount(); i++) { // Determine the name for the HA volume copy. StringBuilder nameBuilder = new StringBuilder(name); nameBuilder.append("-1"); if (copyCount > 1) { nameBuilder.append("-"); nameBuilder.append(copyIndex++); } // Prepare the volume. Volume volume = VPlexBlockServiceApiImpl.prepareVolumeForRequest( size, vplexSystemProject, haVarray, haVpool, haRecommendation.getSourceDevice(), haRecommendation.getSourcePool(), nameBuilder.toString(), null, taskId, _dbClient); volume.addInternalFlags(Flag.INTERNAL_OBJECT); _dbClient.persistObject(volume); copyHAVolumes.add(volume); // Create the volume descriptor and add it to the passed list. VolumeDescriptor volumeDescriptor = new VolumeDescriptor( VolumeDescriptor.Type.BLOCK_DATA, volume.getStorageController(), volume.getId(), volume.getPool(), haCapabilities); volumeDescriptors.add(volumeDescriptor); } } return copyHAVolumes; }
/** * Updates Bucket values like Quota and Retention. * * @param id Bucket ID * @param param Bucket update parameter * @return Task resource representation * @throws InternalException if update fails */ @PUT @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("/{id}") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @CheckPermission( roles = {Role.TENANT_ADMIN}, acls = {ACL.OWN, ACL.ALL}) public TaskResourceRep updateBucket(@PathParam("id") URI id, BucketUpdateParam param) throws InternalException { Bucket bucket = null; ArgValidator.checkFieldUriType(id, Bucket.class, "id"); bucket = _dbClient.queryObject(Bucket.class, id); ArgValidator.checkEntity(bucket, id, isIdEmbeddedInURL(id)); Long softQuota = SizeUtil.translateSize(param.getSoftQuota()); Long hardQuota = SizeUtil.translateSize(param.getHardQuota()); Integer retention = null != param.getRetention() ? Integer.valueOf(param.getRetention()) : 0; // if no softquota is provided, use the old value if (softQuota == 0) { softQuota = bucket.getSoftQuota(); } // if no hardquota is provided, use the old value if (hardQuota == 0) { hardQuota = bucket.getHardQuota(); } // Hard Quota should be more than SoftQuota verifyQuotaValues(softQuota, hardQuota, bucket.getLabel()); // if no retention is provided, use the old value if (retention == 0) { retention = bucket.getRetention(); } VirtualPool cos = _dbClient.queryObject(VirtualPool.class, bucket.getVirtualPool()); // 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"); } String task = UUID.randomUUID().toString(); _log.info(String.format("BucketUpdate --- Bucket id: %1$s, Task: %2$s", id, task)); StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, bucket.getStorageDevice()); Operation op = _dbClient.createTaskOpStatus( Bucket.class, bucket.getId(), task, ResourceOperationTypeEnum.UPDATE_BUCKET); op.setDescription("Bucket update"); ObjectController controller = getController(ObjectController.class, storageSystem.getSystemType()); controller.updateBucket(bucket.getStorageDevice(), id, softQuota, hardQuota, retention, task); auditOp( OperationTypeEnum.UPDATE_BUCKET, true, AuditLogManager.AUDITOP_BEGIN, bucket.getId().toString(), bucket.getStorageDevice().toString()); return toTask(bucket, task, op); }
/** * 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); }
public String getVPoolName() { return vPool.getLabel(); }
// replace all Special Characters ; /-+!@#$%^&())";:[]{}\ | public String getVPoolNameWithNoSpecialCharacters() { return stripSpecialCharacters(vPool.getLabel()); }
/** * 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); }
/** * Updates the initiator to target list map in the export mask * * @throws Exception */ private void updateTargetsInExportMask( StorageSystem storage, Volume volume, Map<Volume, Map<String, List<String>>> volumeToInitiatorTargetMapFromAttachResponse, List<Initiator> fcInitiatorList, ExportMask exportMask) throws Exception { log.debug("START - updateTargetsInExportMask"); // ITLS for initiator URIs vs Target port URIs - This will be the final // filtered list to send for the zoning map update Map<URI, List<URI>> mapFilteredInitiatorURIVsTargetURIList = new HashMap<URI, List<URI>>(); // From the initiators list, construct the map of initiator WWNs to // their URIs Map<String, URI> initiatorsWWNVsURI = getWWNvsURIFCInitiatorsMap(fcInitiatorList); URI varrayURI = volume.getVirtualArray(); /* * Get the list of storage ports from the storage system which are * associated with the varray This will be map of storage port WWNs with * their URIs */ Map<String, URI> mapVarrayTaggedPortWWNVsURI = getVarrayTaggedStoragePortWWNs(storage, varrayURI); // List of WWN entries, used below for filtering the target port list // from attach response Set<String> varrayTaggedPortWWNs = mapVarrayTaggedPortWWNVsURI.keySet(); URI vpoolURI = volume.getVirtualPool(); VirtualPool vpool = dbClient.queryObject(VirtualPool.class, vpoolURI); int pathsPerInitiator = vpool.getPathsPerInitiator(); // Process the attach response output Set<Volume> volumeKeysSet = volumeToInitiatorTargetMapFromAttachResponse.keySet(); for (Volume volumeRes : volumeKeysSet) { log.info( String.format( "Processing attach response for the volume with URI %s and name %s", volumeRes.getId(), volumeRes.getLabel())); Map<String, List<String>> initiatorTargetMap = volumeToInitiatorTargetMapFromAttachResponse.get(volumeRes); Set<String> initiatorKeysSet = initiatorTargetMap.keySet(); for (String initiatorKey : initiatorKeysSet) { // The list of filtered target ports ( which are varray tagged ) // from the attach response List<String> filteredTargetList = filterTargetsFromResponse(varrayTaggedPortWWNs, initiatorTargetMap, initiatorKey); log.info( String.format( "For initiator %s accessible storage ports are %s ", initiatorKey, filteredTargetList.toString())); List<String> tmpTargetList = null; if (!isVplex(volumeRes)) { // For VPLEX - no path validations // Path validations are required only for the Host Exports tmpTargetList = checkPathsPerInitiator(pathsPerInitiator, filteredTargetList); if (null == tmpTargetList) { // Rollback case - throw the exception throw new Exception( String.format( "Paths per initiator criteria is not met for the initiator : %s " + " Target counts is: %s Expected paths per initiator is: %s", initiatorKey, String.valueOf(filteredTargetList.size()), String.valueOf(pathsPerInitiator))); } } else { tmpTargetList = filteredTargetList; } // Now populate URIs for the map to be returned - convert WWNs // to URIs populateInitiatorTargetURIMap( mapFilteredInitiatorURIVsTargetURIList, initiatorsWWNVsURI, mapVarrayTaggedPortWWNVsURI, initiatorKey, tmpTargetList); } // End initiator iteration } // End volume iteration // Clean all existing targets in the export mask and add new targets List<URI> storagePortListFromMask = StringSetUtil.stringSetToUriList(exportMask.getStoragePorts()); for (URI removeUri : storagePortListFromMask) { exportMask.removeTarget(removeUri); } exportMask.setStoragePorts(null); // Now add new target ports and populate the zoning map Set<URI> initiatorURIKeys = mapFilteredInitiatorURIVsTargetURIList.keySet(); for (URI initiatorURI : initiatorURIKeys) { List<URI> storagePortURIList = mapFilteredInitiatorURIVsTargetURIList.get(initiatorURI); for (URI portURI : storagePortURIList) { exportMask.addTarget(portURI); } } log.debug("END - updateTargetsInExportMask"); }
/** * * Check if the request is for vplex. * * @param volume * @return */ private boolean isVplex(Volume volume) { boolean isVplex = false; VirtualPool vpool = dbClient.queryObject(VirtualPool.class, volume.getVirtualPool()); isVplex = VirtualPool.vPoolSpecifiesHighAvailability(vpool); return isVplex; }
/** * 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()); } } } }