Search in sources :

Example 36 with StoragePortGroup

use of com.emc.storageos.db.client.model.StoragePortGroup in project coprhd-controller by CoprHD.

the class BlockService method createVolume.

/**
 * The fundamental abstraction in the Block Store is a
 * volume. A volume is a unit of block storage capacity that has been
 * allocated by a consumer to a project. This API allows the user to
 * create one or more volumes. The volumes are created in the same
 * storage pool.
 *
 * NOTE: This is an asynchronous operation.
 *
 * @prereq none
 *
 * @param param
 *            POST data containing the volume creation information.
 *
 * @brief Create volume
 * @return A reference to a BlockTaskList containing a list of
 *         TaskResourceRep references specifying the task data for the
 *         volume creation tasks.
 * @throws InternalException
 */
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public TaskList createVolume(VolumeCreate param) throws InternalException {
    ArgValidator.checkFieldNotNull(param, "volume_create");
    // CQECC00604134
    ArgValidator.checkFieldUriType(param.getProject(), Project.class, "project");
    // Get and validate the project.
    Project project = _permissionsHelper.getObjectById(param.getProject(), Project.class);
    ArgValidator.checkEntity(project, param.getProject(), isIdEmbeddedInURL(param.getProject()));
    // Verify the user is authorized.
    BlockServiceUtils.verifyUserIsAuthorizedForRequest(project, getUserFromContext(), _permissionsHelper);
    // Get and validate the varray
    ArgValidator.checkFieldUriType(param.getVarray(), VirtualArray.class, "varray");
    VirtualArray varray = BlockServiceUtils.verifyVirtualArrayForRequest(project, param.getVarray(), uriInfo, _permissionsHelper, _dbClient);
    ArgValidator.checkEntity(varray, param.getVarray(), isIdEmbeddedInURL(param.getVarray()));
    // Get and validate the VirtualPool.
    VirtualPool vpool = getVirtualPoolForVolumeCreateRequest(project, param);
    VirtualPoolCapabilityValuesWrapper capabilities = new VirtualPoolCapabilityValuesWrapper();
    // Get the count indicating the number of volumes to create. If not
    // passed
    // assume 1. Then get the volume placement recommendations.
    Integer volumeCount = 1;
    Long volumeSize = 0L;
    if (param.getCount() != null) {
        if (param.getCount() <= 0) {
            throw APIException.badRequests.parameterMustBeGreaterThan("count", 0);
        }
        if (param.getCount() > MAX_VOLUME_COUNT) {
            throw APIException.badRequests.exceedingLimit("count", MAX_VOLUME_COUNT);
        }
        volumeCount = param.getCount();
        capabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, volumeCount);
    }
    if (param.getSize() != null) {
        // Validate the requested volume size is greater then 0.
        volumeSize = SizeUtil.translateSize(param.getSize());
        if (volumeSize <= 0) {
            throw APIException.badRequests.parameterMustBeGreaterThan(SIZE, 0);
        }
        capabilities.put(VirtualPoolCapabilityValuesWrapper.SIZE, volumeSize);
    }
    if (null != vpool.getThinVolumePreAllocationPercentage() && 0 < vpool.getThinVolumePreAllocationPercentage()) {
        capabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_VOLUME_PRE_ALLOCATE_SIZE, VirtualPoolUtil.getThinVolumePreAllocationSize(vpool.getThinVolumePreAllocationPercentage(), volumeSize));
    }
    if (VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(vpool.getSupportedProvisioningType())) {
        capabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, Boolean.TRUE);
    }
    // Does vpool supports dedup
    if (null != vpool.getDedupCapable() && vpool.getDedupCapable()) {
        capabilities.put(VirtualPoolCapabilityValuesWrapper.DEDUP, Boolean.TRUE);
    }
    // Validate the port group
    URI portGroupURI = param.getPortGroup();
    if (!NullColumnValueGetter.isNullURI(portGroupURI)) {
        ArgValidator.checkFieldUriType(portGroupURI, StoragePortGroup.class, "portGroup");
        StoragePortGroup portGroup = _dbClient.queryObject(StoragePortGroup.class, portGroupURI);
        if (portGroup == null || !RegistrationStatus.REGISTERED.name().equalsIgnoreCase(portGroup.getRegistrationStatus())) {
            throw APIException.internalServerErrors.invalidObject(portGroupURI.toString());
        }
        // check if port group's storage system is associated to the requested virtual array
        ExportUtils.validatePortGroupWithVirtualArray(portGroup, varray.getId(), _dbClient);
        capabilities.put(VirtualPoolCapabilityValuesWrapper.PORT_GROUP, portGroupURI);
    }
    // Find the implementation that services this vpool and volume request
    BlockServiceApi blockServiceImpl = getBlockServiceImpl(vpool, _dbClient);
    BlockConsistencyGroup consistencyGroup = null;
    final Boolean isMultiVolumeConsistencyOn = vpool.getMultivolumeConsistency() == null ? FALSE : vpool.getMultivolumeConsistency();
    /*
         * Validate Consistency Group:
         * 1. CG should be active in the database
         * 2. CG project and Volume project should match
         * 3. The storage system that the CG is bonded to is associated to the
         * request virtual array
         */
    ArrayList<String> requestedTypes = new ArrayList<String>();
    final URI actualId = project.getId();
    if (param.getConsistencyGroup() != null) {
        // Get and validate consistency group
        consistencyGroup = queryConsistencyGroup(param.getConsistencyGroup());
        // Check that the Volume project and the CG project are the same
        final URI expectedId = consistencyGroup.getProject().getURI();
        checkProjectsMatch(expectedId, actualId);
        // attribute should be true
        if (!isMultiVolumeConsistencyOn) {
            throw APIException.badRequests.invalidParameterConsistencyGroupProvidedButVirtualPoolHasNoMultiVolumeConsistency(param.getConsistencyGroup(), param.getVpool());
        }
        // Find all volumes assigned to the group
        final List<Volume> activeCGVolumes = blockServiceImpl.getActiveCGVolumes(consistencyGroup);
        // Validate that the number of volumes in the group plus the number
        // to be added by this request does not exceed the maximum volumes
        // in a CG.
        int cgMaxVolCount = blockServiceImpl.getMaxVolumesForConsistencyGroup(consistencyGroup);
        if ((activeCGVolumes.size() + volumeCount.intValue()) > cgMaxVolCount) {
            throw APIException.badRequests.requestedVolumeCountExceedsLimitsForCG(volumeCount.intValue(), cgMaxVolCount, consistencyGroup.getLabel());
        }
        // Get the requested types for provisioning (RP, VPlex, etc.)
        requestedTypes = getRequestedTypes(vpool);
        // If the consistency group is not yet created, verify the name is OK.
        if (!consistencyGroup.created()) {
            blockServiceImpl.validateConsistencyGroupName(consistencyGroup, requestedTypes);
        }
        // Consistency Group is already a Target, hence cannot be used to create source volume
        if (consistencyGroup.srdfTarget()) {
            throw APIException.badRequests.consistencyGroupBelongsToTarget(consistencyGroup.getId());
        }
        if (VirtualPool.vPoolSpecifiesSRDF(vpool) && (consistencyGroup.getLabel().length() > 8 || !isAlphaNumeric(consistencyGroup.getLabel()))) {
            throw APIException.badRequests.groupNameCannotExceedEightCharactersoronlyAlphaNumericAllowed();
        }
        if (!VirtualPool.vPoolSpecifiesSRDF(vpool) && consistencyGroup.checkForType(Types.SRDF)) {
            throw APIException.badRequests.nonSRDFVolumeCannotbeAddedToSRDFCG();
        }
        if (VirtualPool.vPoolSpecifiesSRDF(vpool)) {
            List<Volume> nativeVolumesInCG = BlockConsistencyGroupUtils.getActiveNativeVolumesInCG(consistencyGroup, _dbClient);
            for (Volume nativeVolume : nativeVolumesInCG) {
                // Cannot add volumes if in swapped state. This is a limitation that will eventually be removed.
                if (Volume.LinkStatus.SWAPPED.name().equals(nativeVolume.getLinkStatus())) {
                    throw BadRequestException.badRequests.cannotAddVolumesToSwappedCG(consistencyGroup.getLabel());
                }
            }
        }
        // check if CG's storage system is associated to the requested virtual array
        validateCGValidWithVirtualArray(consistencyGroup, varray);
        // the CG's previously requested types.
        if (consistencyGroup.creationInitiated()) {
            if (!consistencyGroup.getRequestedTypes().containsAll(requestedTypes)) {
                throw APIException.badRequests.consistencyGroupIsNotCompatibleWithRequest(consistencyGroup.getId(), consistencyGroup.getRequestedTypes().toString(), requestedTypes.toString());
            }
        }
        Volume existingRpSourceVolume = null;
        // RP consistency group validation
        if (VirtualPool.vPoolSpecifiesProtection(vpool)) {
            // Check to see if the CG has any RecoverPoint provisioned volumes. This is done by looking at the protectionSet field.
            // The protectionSet field won't be set until the volume is provisioned in RP so this check allows concurrent
            // requests to go through.
            boolean cgHasRpProvisionedVolumes = false;
            if (activeCGVolumes != null && !activeCGVolumes.isEmpty()) {
                for (Volume vol : activeCGVolumes) {
                    if (!NullColumnValueGetter.isNullNamedURI(vol.getProtectionSet())) {
                        _log.info(String.format("Determined that consistency group %s contains RP provisioned volumes.", consistencyGroup.getId()));
                        cgHasRpProvisionedVolumes = true;
                        break;
                    }
                }
            }
            // Ensure the CG is either empty or has been tagged for RP and contains properly provisioned RP volumes.
            if (cgHasRpProvisionedVolumes && !consistencyGroup.getTypes().contains(BlockConsistencyGroup.Types.RP.toString())) {
                throw APIException.badRequests.consistencyGroupMustBeEmptyOrContainRpVolumes(consistencyGroup.getId());
            }
            if (!activeCGVolumes.isEmpty()) {
                // Find the first existing source volume for source/target varray comparison.
                for (Volume cgVolume : activeCGVolumes) {
                    if (cgVolume.getPersonality() != null && cgVolume.getPersonality().equals(Volume.PersonalityTypes.SOURCE.toString())) {
                        existingRpSourceVolume = cgVolume;
                        break;
                    }
                }
                if (existingRpSourceVolume != null) {
                    VirtualPool existingVpool = _dbClient.queryObject(VirtualPool.class, existingRpSourceVolume.getVirtualPool());
                    VirtualPool requestedVpool = _dbClient.queryObject(VirtualPool.class, param.getVpool());
                    // The source virtual arrays must much
                    if (existingVpool.getVirtualArrays().size() != requestedVpool.getVirtualArrays().size() || !existingVpool.getVirtualArrays().containsAll(requestedVpool.getVirtualArrays())) {
                        // The source virtual arrays are not compatible with the CG
                        throw APIException.badRequests.vPoolSourceVarraysNotCompatibleForCG(consistencyGroup.getLabel());
                    }
                    // MetroPoint volumes in the same CG.
                    if (VirtualPool.vPoolSpecifiesHighAvailability(existingVpool) && VirtualPool.vPoolSpecifiesHighAvailability(requestedVpool)) {
                        // that we are not trying to mix MetroPoint volumes with Metro volumes.
                        if ((!VirtualPool.vPoolSpecifiesMetroPoint(requestedVpool) && VirtualPool.vPoolSpecifiesMetroPoint(existingVpool)) || (VirtualPool.vPoolSpecifiesMetroPoint(requestedVpool) && !VirtualPool.vPoolSpecifiesMetroPoint(existingVpool))) {
                            throw APIException.badRequests.cannotMixMetroPointAndNonMetroPointVolumes(consistencyGroup.getLabel());
                        }
                    }
                    // Check the target virtual arrays
                    StringMap existingProtectionVarraySettings = existingVpool.getProtectionVarraySettings();
                    if (existingProtectionVarraySettings == null) {
                        // NOTE: This will be supported in the future through Jira CTRL-10129
                        throw APIException.badRequests.cannotAddVolumesToSwappedCG(consistencyGroup.getLabel());
                    }
                    StringMap requestedProtectionVarraySettings = requestedVpool.getProtectionVarraySettings();
                    if (existingProtectionVarraySettings.size() != requestedProtectionVarraySettings.size()) {
                        // The target virtual arrays are not compatible with the CG
                        throw APIException.badRequests.vPoolTargetVarraysNotCompatibleForCG(consistencyGroup.getLabel());
                    }
                    for (String targetVarray : requestedProtectionVarraySettings.keySet()) {
                        if (!existingProtectionVarraySettings.containsKey(targetVarray)) {
                            // The target virtual arrays are not compatible with the CG
                            throw APIException.badRequests.vPoolTargetVarraysNotCompatibleForCG(consistencyGroup.getLabel());
                        }
                    }
                    // Ensure the replication mode is logically equivalent
                    String requestedRpCopyMode = NullColumnValueGetter.isNullValue(requestedVpool.getRpCopyMode()) ? RPCopyMode.ASYNCHRONOUS.name() : requestedVpool.getRpCopyMode();
                    String existingRpCopyMode = NullColumnValueGetter.isNullValue(existingVpool.getRpCopyMode()) ? RPCopyMode.ASYNCHRONOUS.name() : existingVpool.getRpCopyMode();
                    if (!requestedRpCopyMode.equalsIgnoreCase(existingRpCopyMode)) {
                        throw APIException.badRequests.vPoolRPCopyModeNotCompatibleForCG(consistencyGroup.getLabel());
                    }
                }
            }
        }
        // are still attached to their source volumes.
        if (!activeCGVolumes.isEmpty()) {
            // Pass in an active CG volume for validation. If we are dealing with a RecoverPoint
            // consistency group, we need to use an RP source volume. Otherwise we can use any arbitrary
            // CG volume.
            Volume activeCGVolume = existingRpSourceVolume == null ? activeCGVolumes.get(0) : existingRpSourceVolume;
            if (!BlockServiceUtils.checkCGVolumeCanBeAddedOrRemoved(consistencyGroup, activeCGVolume, _dbClient)) {
                checkCGForMirrors(consistencyGroup, activeCGVolumes);
                checkCGForSnapshots(consistencyGroup);
                getFullCopyManager().verifyNewVolumesCanBeCreatedInConsistencyGroup(consistencyGroup, activeCGVolumes);
            }
        }
        capabilities.put(VirtualPoolCapabilityValuesWrapper.BLOCK_CONSISTENCY_GROUP, param.getConsistencyGroup());
    } else if (VirtualPool.vPoolSpecifiesProtection(vpool)) {
        // protection is specified, a consistency group must be selected.
        throw APIException.badRequests.consistencyGroupMissingForRpProtection();
    }
    // verify quota
    long size = volumeCount * SizeUtil.translateSize(param.getSize());
    TenantOrg tenant = _dbClient.queryObject(TenantOrg.class, project.getTenantOrg().getURI());
    ArgValidator.checkEntity(tenant, project.getTenantOrg().getURI(), false);
    CapacityUtils.validateQuotasForProvisioning(_dbClient, vpool, project, tenant, size, "volume");
    // set compute param
    URI computeURI = param.getComputeResource();
    if (!NullColumnValueGetter.isNullURI(computeURI)) {
        capabilities.put(VirtualPoolCapabilityValuesWrapper.COMPUTE, computeURI.toString());
    }
    // COP-14028
    // Changing the return of a TaskList to return immediately while the underlying tasks are
    // being built up. Steps:
    // 1. Create a task object ahead of time and persist it for each requested volume.
    // 2. Fire off a thread that does the placement and preparation of the volumes, which will use the pre-created
    // task/volume objects during their source volume creations.
    // 3. Return to the caller the new Task objects that is in the pending state.
    String task = UUID.randomUUID().toString();
    TaskList taskList = createVolumeTaskList(param.getSize(), project, varray, vpool, param.getName(), task, volumeCount);
    // This is causing exceptions when run in the thread.
    auditOp(OperationTypeEnum.CREATE_BLOCK_VOLUME, true, AuditLogManager.AUDITOP_BEGIN, param.getName(), volumeCount, varray.getId().toString(), actualId.toString());
    // call thread that does the work.
    CreateVolumeSchedulingThread.executeApiTask(this, _asyncTaskService.getExecutorService(), _dbClient, varray, project, vpool, capabilities, taskList, task, consistencyGroup, requestedTypes, param, blockServiceImpl);
    _log.info("Kicked off thread to perform placement and scheduling.  Returning " + taskList.getTaskList().size() + " tasks");
    return taskList;
}
Also used : VirtualPoolCapabilityValuesWrapper(com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper) StoragePortGroup(com.emc.storageos.db.client.model.StoragePortGroup) VirtualArray(com.emc.storageos.db.client.model.VirtualArray) StringMap(com.emc.storageos.db.client.model.StringMap) TaskList(com.emc.storageos.model.TaskList) ArrayList(java.util.ArrayList) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) URI(java.net.URI) NullColumnValueGetter.isNullURI(com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI) PrefixConstraint(com.emc.storageos.db.client.constraint.PrefixConstraint) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) ContainmentPrefixConstraint(com.emc.storageos.db.client.constraint.ContainmentPrefixConstraint) ContainmentConstraint(com.emc.storageos.db.client.constraint.ContainmentConstraint) Constraint(com.emc.storageos.db.client.constraint.Constraint) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup) Project(com.emc.storageos.db.client.model.Project) MapVolume(com.emc.storageos.api.mapper.functions.MapVolume) Volume(com.emc.storageos.db.client.model.Volume) TenantOrg(com.emc.storageos.db.client.model.TenantOrg) Boolean.parseBoolean(java.lang.Boolean.parseBoolean) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces)

Example 37 with StoragePortGroup

use of com.emc.storageos.db.client.model.StoragePortGroup in project coprhd-controller by CoprHD.

the class StorageScheduler method getMatchingPools.

/**
 * Select candidate storage pools for placement.
 *
 * @param varray The VirtualArray for matching storage pools.
 * @param vpool The virtualPool that must be satisfied by the storage pool.
 * @param capabilities The VirtualPool params that must be satisfied.
 * @param optionalAttributes Optional addition attributes to consider for placement
 *
 * @return A list of matching storage pools.
 */
protected List<StoragePool> getMatchingPools(VirtualArray varray, VirtualPool vpool, VirtualPoolCapabilityValuesWrapper capabilities, Map<String, Object> optionalAttributes) {
    capabilities.put(VirtualPoolCapabilityValuesWrapper.VARRAYS, varray.getId().toString());
    if (null != vpool.getAutoTierPolicyName()) {
        capabilities.put(VirtualPoolCapabilityValuesWrapper.AUTO_TIER__POLICY_NAME, vpool.getAutoTierPolicyName());
    }
    List<StoragePool> storagePools = new ArrayList<StoragePool>();
    String varrayId = varray.getId().toString();
    StringBuffer errorMessage = new StringBuffer();
    // Verify that if the VirtualPool has been assigned one or more VirtualArrays,
    // there is a match with the passed VirtualArray.
    StringSet vpoolVarrays = vpool.getVirtualArrays();
    if ((vpoolVarrays != null) && (!vpoolVarrays.contains(varrayId))) {
        String message = String.format("Virtual Array %s is not assigned to Virtual Pool %s. ", varray.forDisplay(), vpool.forDisplay());
        errorMessage.append(message);
        _log.error(message);
        if (optionalAttributes != null) {
            optionalAttributes.put(AttributeMatcher.ERROR_MESSAGE, errorMessage);
        }
        return storagePools;
    }
    // Get pools for VirtualPool and VirtualArray
    List<StoragePool> matchedPoolsForCos = VirtualPool.getValidStoragePools(vpool, _dbClient, true);
    if (matchedPoolsForCos.isEmpty()) {
        _log.warn("vPool {} does not have any valid storage pool in vArray {}.", vpool.getId(), varray.getId());
        throw APIException.badRequests.noStoragePoolsForVpoolInVarray(varray.getLabel(), vpool.getLabel());
    }
    AttributeMapBuilder provMapBuilder = new ProvisioningAttributeMapBuilder(capabilities.getSize(), varrayId, capabilities.getThinVolumePreAllocateSize());
    provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.provisioning_type.toString(), vpool.getSupportedProvisioningType());
    // Set CG related attributes for placement
    final BlockConsistencyGroup consistencyGroup = capabilities.getBlockConsistencyGroup() == null ? null : _dbClient.queryObject(BlockConsistencyGroup.class, capabilities.getBlockConsistencyGroup());
    if (consistencyGroup != null) {
        URI cgStorageSystemURI = consistencyGroup.getStorageController();
        if (!NullColumnValueGetter.isNullURI(cgStorageSystemURI)) {
            StorageSystem cgStorageSystem = _dbClient.queryObject(StorageSystem.class, cgStorageSystemURI);
            Set<String> storageSystemSet = new HashSet<String>();
            // this logic is added, as we don't want to add any relationships between source and target CGs explicitly in ViPR.
            if (VirtualPoolCapabilityValuesWrapper.SRDF_TARGET.equalsIgnoreCase(capabilities.getPersonality())) {
                // then update storage system corresponding to target CG
                // source Label is set as alternate name for target Cgs, so that the same name can be used to create targte CGs in
                // Array.
                List<URI> cgUris = _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getBlockConsistencyGroupByAlternateNameConstraint(consistencyGroup.getLabel()));
                if (!cgUris.isEmpty()) {
                    BlockConsistencyGroup targetCgGroup = _dbClient.queryObject(BlockConsistencyGroup.class, cgUris.get(0));
                    if (null != targetCgGroup && !targetCgGroup.getInactive() && null != targetCgGroup.getStorageController() && !NullColumnValueGetter.isNullURI(targetCgGroup.getStorageController())) {
                        storageSystemSet.add(targetCgGroup.getStorageController().toString());
                        provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
                        provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
                    }
                }
            } else if (!DiscoveredDataObject.Type.vplex.name().equals(cgStorageSystem.getSystemType())) {
                // If this is not a VPLEX CG, add the ConsistencyGroup's StorageSystem
                // so that the matching pools are in the same system
                storageSystemSet.add(cgStorageSystemURI.toString());
                provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
                provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
                // IBM XIV requires all volumes of a CG in the same StoragePool
                if (DiscoveredDataObject.Type.ibmxiv.name().equals(cgStorageSystem.getSystemType())) {
                    List<Volume> activeCGVolumes = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, Volume.class, AlternateIdConstraint.Factory.getBlockObjectsByConsistencyGroup(consistencyGroup.getId().toString()));
                    if (!activeCGVolumes.isEmpty()) {
                        URI cgPoolURI = activeCGVolumes.get(0).getPool();
                        if (!NullColumnValueGetter.isNullURI(cgPoolURI)) {
                            Iterator<StoragePool> itr = matchedPoolsForCos.iterator();
                            while (itr.hasNext()) {
                                // remove all pools from matchedPoolsForCos except the one matched
                                URI poolURI = itr.next().getId();
                                if (!cgPoolURI.equals(poolURI)) {
                                    _log.debug("Remove pool {} from list", poolURI);
                                    itr.remove();
                                }
                            }
                        }
                        if (!matchedPoolsForCos.isEmpty()) {
                            _log.debug("Pool {} is used by CG {}", cgPoolURI, consistencyGroup.getId());
                        } else {
                            _log.warn("vPool {} does not have required IBM XIV storage pool in vArray {}.", vpool.getId(), varray.getId());
                            throw APIException.badRequests.noStoragePoolsForVpoolInVarray(varray.getLabel(), vpool.getLabel());
                        }
                    }
                }
            } else {
                provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
            }
        } else {
            provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
        }
    }
    // This is used by the VPLEX to control consistency groups.
    if (capabilities.getSourceStorageDevice() != null) {
        StorageSystem sourceStorageSystem = capabilities.getSourceStorageDevice();
        Set<String> storageSystemSet = new HashSet<String>();
        storageSystemSet.add(sourceStorageSystem.getId().toString());
        provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
    } else if (capabilities.getExcludedStorageDevice() != null) {
        StorageSystem excludedStorageSystem = capabilities.getExcludedStorageDevice();
        Set<String> storageSystemSet = new HashSet<String>();
        storageSystemSet.add(excludedStorageSystem.getId().toString());
        provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.exclude_storage_system.name(), storageSystemSet);
    }
    // populate DriveType,and Raid level and Policy Name for FAST Initial Placement Selection
    provMapBuilder.putAttributeInMap(Attributes.auto_tiering_policy_name.toString(), vpool.getAutoTierPolicyName());
    provMapBuilder.putAttributeInMap(Attributes.unique_policy_names.toString(), vpool.getUniquePolicyNames());
    provMapBuilder.putAttributeInMap(AttributeMatcher.PLACEMENT_MATCHERS, true);
    provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.drive_type.name(), vpool.getDriveType());
    StringSetMap arrayInfo = vpool.getArrayInfo();
    if (null != arrayInfo) {
        Set<String> raidLevels = arrayInfo.get(VirtualPoolCapabilityValuesWrapper.RAID_LEVEL);
        if (null != raidLevels && !raidLevels.isEmpty()) {
            provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.raid_levels.name(), raidLevels);
        }
        Set<String> systemTypes = arrayInfo.get(AttributeMatcher.Attributes.system_type.name());
        if (null != systemTypes && !systemTypes.isEmpty()) {
            provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.system_type.name(), systemTypes);
            // put quota value for ecs storage
            if (systemTypes.contains("ecs") && capabilities.getQuota() != null) {
                provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.quota.name(), capabilities.getQuota());
            }
        }
    }
    Map<URI, VpoolRemoteCopyProtectionSettings> remoteProtectionSettings = vpool.getRemoteProtectionSettings(vpool, _dbClient);
    if (null != remoteProtectionSettings && !remoteProtectionSettings.isEmpty()) {
        provMapBuilder.putAttributeInMap(Attributes.remote_copy.toString(), VirtualPool.groupRemoteCopyModesByVPool(vpool.getId(), remoteProtectionSettings));
    }
    if (VirtualPoolCapabilityValuesWrapper.FILE_REPLICATION_SOURCE.equalsIgnoreCase(capabilities.getPersonality())) {
        // Run the placement algorithm for file replication!!!
        if (capabilities.getFileReplicationType() != null && !FileReplicationType.NONE.name().equalsIgnoreCase(capabilities.getFileReplicationType())) {
            provMapBuilder.putAttributeInMap(Attributes.file_replication_type.toString(), capabilities.getFileReplicationType());
            if (capabilities.getFileRpCopyMode() != null) {
                provMapBuilder.putAttributeInMap(Attributes.file_replication_copy_mode.toString(), capabilities.getFileRpCopyMode());
            }
            if (capabilities.getFileReplicationTargetVArrays() != null) {
                provMapBuilder.putAttributeInMap(Attributes.file_replication_target_varray.toString(), capabilities.getFileReplicationTargetVArrays());
            }
            if (capabilities.getFileReplicationTargetVPool() != null) {
                provMapBuilder.putAttributeInMap(Attributes.file_replication_target_vpool.toString(), capabilities.getFileReplicationTargetVPool());
            }
        }
    }
    if (capabilities.getSupportsSoftLimit()) {
        provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.support_soft_limit.name(), capabilities.getSupportsSoftLimit());
    }
    if (capabilities.getSupportsNotificationLimit()) {
        provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.support_notification_limit.name(), capabilities.getSupportsNotificationLimit());
    }
    if (!(VirtualPool.vPoolSpecifiesProtection(vpool) || VirtualPool.vPoolSpecifiesSRDF(vpool) || VirtualPool.vPoolSpecifiesHighAvailability(vpool) || VirtualPool.vPoolSpecifiesHighAvailabilityDistributed(vpool))) {
        // only enforce array affinity policy for vpool without RP, SRDF, VPLEX
        boolean arrayAffinity = VirtualPool.ResourcePlacementPolicyType.array_affinity.name().equals(vpool.getPlacementPolicy());
        if (arrayAffinity && capabilities.getCompute() != null) {
            capabilities.put(VirtualPoolCapabilityValuesWrapper.ARRAY_AFFINITY, true);
            provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.array_affinity.name(), true);
        }
    }
    URI portGroupURI = capabilities.getPortGroup();
    boolean usePortGroup = !NullColumnValueGetter.isNullURI(portGroupURI);
    if (usePortGroup) {
        if (!VirtualPool.vPoolSpecifiesHighAvailability(vpool)) {
            StoragePortGroup portGroup = _dbClient.queryObject(StoragePortGroup.class, portGroupURI);
            URI pgSystemURI = portGroup.getStorageDevice();
            boolean setSystemMatcher = true;
            if (consistencyGroup != null) {
                URI cgSystemURI = consistencyGroup.getStorageController();
                if (!NullColumnValueGetter.isNullURI(cgSystemURI)) {
                    if (!cgSystemURI.equals(pgSystemURI)) {
                        // consistency group and port group does not belong to the same storage system
                        throw APIException.badRequests.cgPortGroupNotMatch(portGroupURI.toString(), consistencyGroup.getId().toString());
                    } else {
                        // system matcher has been set
                        setSystemMatcher = false;
                    }
                }
            }
            if (setSystemMatcher) {
                Set<String> storageSystemSet = new HashSet<String>();
                storageSystemSet.add(pgSystemURI.toString());
                provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
            }
        } else {
            // port group could be only specified for native vmax
            throw APIException.badRequests.portGroupValidForVMAXOnly();
        }
    } else {
        // PG was not supplied. This is normally OK unless the VMAX PG feature in enabled and the vpool is not for VPLEX.
        String value = _customConfigHandler.getComputedCustomConfigValue(CustomConfigConstants.VMAX_USE_PORT_GROUP_ENABLED, Type.vmax.name(), null);
        if (Boolean.TRUE.toString().equalsIgnoreCase(value) && !VirtualPool.vPoolSpecifiesHighAvailability(vpool)) {
            // VMAX PG feature is enabled. Limit the valid storage pools to those not requiring PG.
            limitToStoragePoolsNotRequiringPortGroup(capabilities, vpool, provMapBuilder);
        }
    }
    Map<String, Object> attributeMap = provMapBuilder.buildMap();
    if (optionalAttributes != null) {
        attributeMap.putAll(optionalAttributes);
    }
    _log.info("Populated attribute map: {}", attributeMap);
    // Execute basic precondition check to verify that vArray has active storage pools in the vPool.
    // We will return a more accurate error condition if this basic check fails.
    List<StoragePool> matchedPools = _matcherFramework.matchAttributes(matchedPoolsForCos, attributeMap, _dbClient, _coordinator, AttributeMatcher.BASIC_PLACEMENT_MATCHERS, errorMessage);
    if (matchedPools == null || matchedPools.isEmpty()) {
        _log.warn("vPool {} does not have active storage pools in vArray  {} .", vpool.getId(), varray.getId());
        throw APIException.badRequests.noStoragePools(varray.getLabel(), vpool.getLabel(), errorMessage.toString());
    }
    errorMessage.setLength(0);
    // Matches the pools against the VolumeParams.
    // Use a set of matched pools returned from the basic placement matching as the input for this call.
    matchedPools = _matcherFramework.matchAttributes(matchedPools, attributeMap, _dbClient, _coordinator, AttributeMatcher.PLACEMENT_MATCHERS, errorMessage);
    if (matchedPools == null || matchedPools.isEmpty()) {
        if (optionalAttributes != null) {
            optionalAttributes.put(AttributeMatcher.ERROR_MESSAGE, errorMessage);
        }
        _log.warn("Varray {} does not have storage pools which match vpool {} properties and have specified  capabilities.", varray.getId(), vpool.getId());
        return storagePools;
    }
    storagePools.addAll(matchedPools);
    return storagePools;
}
Also used : ProvisioningAttributeMapBuilder(com.emc.storageos.volumecontroller.impl.utils.ProvisioningAttributeMapBuilder) StoragePortGroup(com.emc.storageos.db.client.model.StoragePortGroup) VpoolRemoteCopyProtectionSettings(com.emc.storageos.db.client.model.VpoolRemoteCopyProtectionSettings) StoragePool(com.emc.storageos.db.client.model.StoragePool) Set(java.util.Set) HashSet(java.util.HashSet) StringSet(com.emc.storageos.db.client.model.StringSet) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) StringSet(com.emc.storageos.db.client.model.StringSet) Iterator(java.util.Iterator) List(java.util.List) ArrayList(java.util.ArrayList) TaskList(com.emc.storageos.model.TaskList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) HashSet(java.util.HashSet) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) ProvisioningAttributeMapBuilder(com.emc.storageos.volumecontroller.impl.utils.ProvisioningAttributeMapBuilder) AttributeMapBuilder(com.emc.storageos.volumecontroller.impl.utils.AttributeMapBuilder) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup) Volume(com.emc.storageos.db.client.model.Volume) BlockObject(com.emc.storageos.db.client.model.BlockObject) DiscoveredDataObject(com.emc.storageos.db.client.model.DiscoveredDataObject)

Aggregations

StoragePortGroup (com.emc.storageos.db.client.model.StoragePortGroup)37 URI (java.net.URI)25 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)14 ArrayList (java.util.ArrayList)14 ExportMask (com.emc.storageos.db.client.model.ExportMask)12 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)11 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)11 HashSet (java.util.HashSet)9 WBEMException (javax.wbem.WBEMException)9 Produces (javax.ws.rs.Produces)9 MapStoragePortGroup (com.emc.storageos.api.mapper.functions.MapStoragePortGroup)8 StringSet (com.emc.storageos.db.client.model.StringSet)8 CheckPermission (com.emc.storageos.security.authorization.CheckPermission)8 Path (javax.ws.rs.Path)8 Initiator (com.emc.storageos.db.client.model.Initiator)7 ExportPathParams (com.emc.storageos.db.client.model.ExportPathParams)6 NamedURI (com.emc.storageos.db.client.model.NamedURI)6 SmisException (com.emc.storageos.volumecontroller.impl.smis.SmisException)6 CIMInstance (javax.cim.CIMInstance)6 CIMObjectPath (javax.cim.CIMObjectPath)6