/** * 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; }
/** * 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); }
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); }
/** * Update Quota Directory for a file share * * <p>NOTE: This is an asynchronous operation. * * @param id the URN of a ViPR Quota directory * @param param File system Quota directory update parameters * @brief Update file system Quota directory * @return Task resource representation * @throws com.emc.storageos.svcs.errorhandling.resources.InternalException */ @POST @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("/{id}") @CheckPermission( roles = {Role.TENANT_ADMIN}, acls = {ACL.OWN, ACL.ALL}) public TaskResourceRep updateQuotaDirectory( @PathParam("id") URI id, QuotaDirectoryUpdateParam param) throws InternalException { _log.info("FileService::Update Quota directory Request recieved {}", id); QuotaDirectory quotaDir = queryResource(id); String task = UUID.randomUUID().toString(); if (param.getSecurityStyle() != null) { ArgValidator.checkFieldValueFromEnum( param.getSecurityStyle(), "security_style", EnumSet.allOf(QuotaDirectory.SecurityStyles.class)); } // Get the FileSystem object FileShare fs = queryFileShareResource(quotaDir.getParent().getURI()); ArgValidator.checkFieldNotNull(fs, "filesystem"); // Update the quota directory object to store in ViPR database quotaDir.setOpStatus(new OpStatusMap()); // Set all other optional parameters too. if (param.getOpLock() != null) { quotaDir.setOpLock(param.getOpLock()); } if (param.getSecurityStyle() != null) { quotaDir.setSecurityStyle(param.getSecurityStyle()); } if (param.getSize() != null) { Long quotaSize = SizeUtil.translateSize(param.getSize()); if (quotaSize > 0) { ArgValidator.checkFieldMaximum(quotaSize, fs.getCapacity(), " Bytes", "size"); quotaDir.setSize(quotaSize); } } Operation op = new Operation(); op.setResourceType(ResourceOperationTypeEnum.UPDATE_FILE_SYSTEM_QUOTA_DIR); quotaDir.getOpStatus().createTaskStatus(task, op); fs.setOpStatus(new OpStatusMap()); fs.getOpStatus().createTaskStatus(task, op); _dbClient.persistObject(fs); _dbClient.persistObject(quotaDir); // Create an object of type "FileShareQtree" to be passed into the south-bound layers. FileShareQuotaDirectory qt = new FileShareQuotaDirectory(quotaDir); // Now get ready to make calls into the controller StorageSystem device = _dbClient.queryObject(StorageSystem.class, fs.getStorageDevice()); FileController controller = getController(FileController.class, device.getSystemType()); try { controller.updateQuotaDirectory(device.getId(), qt, fs.getId(), task); } catch (InternalException e) { _log.error("Error during update of Quota Directory {}", e); // treating all controller exceptions as internal error for now. controller // should discriminate between validation problems vs. internal errors throw e; } auditOp( OperationTypeEnum.UPDATE_FILE_SYSTEM_QUOTA_DIR, true, AuditLogManager.AUDITOP_BEGIN, quotaDir.getLabel(), quotaDir.getId().toString(), fs.getId().toString()); fs = _dbClient.queryObject(FileShare.class, fs.getId()); _log.debug( "FileService::Quota directory Before sending response, FS ID : {}, Taks : {} ; Status {}", fs.getOpStatus().get(task), fs.getOpStatus().get(task).getStatus()); return toTask(quotaDir, task, op); }