Search in sources :

Example 1 with NullColumnValueGetter.isNullURI

use of com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI in project coprhd-controller by CoprHD.

the class VolumeGroupService method checkForApplicationPendingTasks.

/**
 * Check if the application and its CGs/volumes/snapshots/snapshotSessions have any pending tasks
 *
 * @param volumeGroup The volume group
 * @param dbClient
 * @param preventAnyPendingTask If throw error when there is any pending task
 */
private void checkForApplicationPendingTasks(VolumeGroup volumeGroup, DbClient dbClient, boolean preventAnyPendingTask) {
    checkForPendingTask(volumeGroup.getId(), dbClient, preventAnyPendingTask);
    Set<URI> cgs = new HashSet<URI>();
    List<Volume> allVolumes = ControllerUtils.getVolumeGroupVolumes(dbClient, volumeGroup);
    for (Volume vol : allVolumes) {
        checkForPendingTask(vol.getId(), dbClient, preventAnyPendingTask);
        URI cg = vol.getConsistencyGroup();
        if (!NullColumnValueGetter.isNullURI(cg)) {
            cgs.add(vol.getConsistencyGroup());
        }
    }
    for (URI cg : cgs) {
        checkForPendingTask(cg, dbClient, preventAnyPendingTask);
    }
    // it has a corresponding task in CG. so the above checking on CG should cover the case for clone.
    for (Volume volume : allVolumes) {
        Volume theVol = volume;
        if (volume.isVPlexVolume(dbClient)) {
            theVol = VPlexUtil.getVPLEXBackendVolume(volume, true, dbClient);
            if (theVol == null || theVol.getInactive()) {
                log.warn("Cannot find backend volume for VPLEX volume {}", volume.getLabel());
                continue;
            }
        }
        URIQueryResultList snapshotURIs = new URIQueryResultList();
        dbClient.queryByConstraint(ContainmentConstraint.Factory.getVolumeSnapshotConstraint(theVol.getId()), snapshotURIs);
        Iterator<URI> it = snapshotURIs.iterator();
        while (it.hasNext()) {
            URI snapURI = it.next();
            checkForPendingTask(snapURI, dbClient, preventAnyPendingTask);
        }
    }
    // Get snapshotSessions
    List<BlockSnapshotSession> sessions = getVolumeGroupSnapshotSessions(volumeGroup);
    for (BlockSnapshotSession session : sessions) {
        checkForPendingTask(session.getId(), dbClient, preventAnyPendingTask);
    }
}
Also used : BlockSnapshotSession(com.emc.storageos.db.client.model.BlockSnapshotSession) Volume(com.emc.storageos.db.client.model.Volume) URI(java.net.URI) NullColumnValueGetter.isNullURI(com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) HashSet(java.util.HashSet)

Example 2 with NullColumnValueGetter.isNullURI

use of com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI in project coprhd-controller by CoprHD.

the class VolumeGroupService method verifyReplicaForCopyRequest.

/**
 * Verifies that the passed replica URI and ensure that it represents a replica for a volume in volume group represented by
 * the passed
 * in volume group id.
 *
 * @param replica
 *            the replica (Clone/Snapshot/Mirror)
 * @param volumeGroupUri
 * @return The URI of the replica's source.
 */
private URI verifyReplicaForCopyRequest(BlockObject replica, URI volumeGroupUri) {
    URI sourceURI = getSourceIdForFullCopy(replica);
    if (NullColumnValueGetter.isNullURI(sourceURI)) {
        throw APIException.badRequests.replicaOperationNotAllowedNotAReplica(getReplicaType(replica), replica.getLabel());
    }
    Volume sourceVol = _dbClient.queryObject(Volume.class, sourceURI);
    if (sourceVol != null && !sourceVol.getInactive() && sourceVol.getVolumeGroupIds() != null && sourceVol.getVolumeGroupIds().contains(volumeGroupUri.toString())) {
        return sourceURI;
    }
    throw APIException.badRequests.replicaOperationNotAllowedSourceNotInVolumeGroup(getReplicaType(replica), replica.getLabel());
}
Also used : Volume(com.emc.storageos.db.client.model.Volume) URI(java.net.URI) NullColumnValueGetter.isNullURI(com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI)

Example 3 with NullColumnValueGetter.isNullURI

use of com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI in project coprhd-controller by CoprHD.

the class VolumeGroupService method getClonesBySetName.

/**
 * Gets all clones for the given set name and volume group.
 *
 * @param cloneSetName
 * @param volumeGroupId
 * @param dbClient
 * @return
 */
private List<Volume> getClonesBySetName(String cloneSetName, URI volumeGroupId) {
    List<Volume> setClones = new ArrayList<Volume>();
    if (cloneSetName != null) {
        URIQueryResultList list = new URIQueryResultList();
        _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getFullCopiesBySetName(cloneSetName), list);
        Iterator<Volume> iter = _dbClient.queryIterativeObjects(Volume.class, list);
        while (iter.hasNext()) {
            Volume vol = iter.next();
            URI sourceId = getSourceIdForFullCopy(vol);
            if (!NullColumnValueGetter.isNullURI(sourceId)) {
                Volume sourceVol = _dbClient.queryObject(Volume.class, sourceId);
                if (sourceVol != null && !sourceVol.getInactive() && sourceVol.getVolumeGroupIds() != null && sourceVol.getVolumeGroupIds().contains(volumeGroupId.toString())) {
                    setClones.add(vol);
                }
            }
        }
    }
    return setClones;
}
Also used : Volume(com.emc.storageos.db.client.model.Volume) ArrayList(java.util.ArrayList) URI(java.net.URI) NullColumnValueGetter.isNullURI(com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList)

Example 4 with NullColumnValueGetter.isNullURI

use of com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI 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 5 with NullColumnValueGetter.isNullURI

use of com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI in project coprhd-controller by CoprHD.

the class BlockService method changeVirtualArrayForVolumes.

/**
 * Changes the virtual array for the passed volumes to the passed
 * target virtual array.
 *
 * @param volumeURIs
 *            The URIs of the volumes to move
 * @param tgtVarrayURI
 *            The URI of the target virtual array
 *
 * @return A TaskList of the tasks associated with each volume being moved.
 *
 * @throws InternalException,
 *             APIException
 */
private TaskList changeVirtualArrayForVolumes(List<URI> volumeURIs, URI tgtVarrayURI) throws InternalException, APIException {
    // Create the result.
    TaskList taskList = new TaskList();
    // Create a unique task id.
    String taskId = UUID.randomUUID().toString();
    // Validate that each of the volumes passed in is eligible
    // for the varray change.
    VirtualArray tgtVarray = null;
    BlockConsistencyGroup cg = null;
    BlockServiceApi blockServiceAPI = null;
    List<Volume> volumes = new ArrayList<Volume>();
    List<Volume> cgVolumes = new ArrayList<Volume>();
    boolean foundVolumeNotInCG = false;
    for (URI volumeURI : volumeURIs) {
        // Get and verify the volume.
        ArgValidator.checkFieldUriType(volumeURI, Volume.class, "volume");
        Volume volume = queryVolumeResource(volumeURI);
        ArgValidator.checkEntity(volume, volumeURI, false);
        _log.info("Found volume {}", volumeURI);
        // Don't operate on VPLEX backend or RP Journal volumes.
        BlockServiceUtils.validateNotAnInternalBlockObject(volume, false);
        // Don't operate on ingested volumes.
        VolumeIngestionUtil.checkOperationSupportedOnIngestedVolume(volume, ResourceOperationTypeEnum.CHANGE_BLOCK_VOLUME_VARRAY, _dbClient);
        // Get and validate the volume's project.
        URI projectURI = volume.getProject().getURI();
        Project project = _permissionsHelper.getObjectById(projectURI, Project.class);
        ArgValidator.checkEntity(project, projectURI, false);
        _log.info("Found volume project {}", projectURI);
        // Verify the user is authorized for the volume's project.
        BlockServiceUtils.verifyUserIsAuthorizedForRequest(project, getUserFromContext(), _permissionsHelper);
        _log.info("User is authorized for volume's project");
        // Verify the current and requested virtual arrays are not the same.
        if (volume.getVirtualArray().equals(tgtVarrayURI)) {
            throw APIException.badRequests.currentAndRequestedVArrayAreTheSame();
        }
        // Get and validate the target virtual array.
        if (tgtVarray == null) {
            tgtVarray = BlockServiceUtils.verifyVirtualArrayForRequest(project, tgtVarrayURI, uriInfo, _permissionsHelper, _dbClient);
            _log.info("Found new VirtualArray {}", tgtVarrayURI);
        }
        // Make sure that we don't have some pending
        // operation against the volume
        checkForPendingTasks(Arrays.asList(volume.getTenant().getURI()), Arrays.asList(volume));
        // Get the appropriate block service implementation for the
        // volume. Note that this same implementation is used to
        // execute the change. If it is possible that volumes
        // with multiple implementations can be selected for a
        // varray change, then we would need a map of the
        // implementation to use for a given volume. However,
        // currently only VPLEX volumes can be moved, so valid
        // volumes for a varray change will always have the same
        // implementation.
        blockServiceAPI = getBlockServiceImpl(volume);
        // Verify that the virtual array change is allowed for the
        // requested volume and virtual array.
        blockServiceAPI.verifyVarrayChangeSupportedForVolumeAndVarray(volume, tgtVarray);
        _log.info("Virtual array change is supported for requested volume and varray");
        // All volumes must be a CG or none of the volumes can be
        // in a CG. After processing individual volumes, if the
        // volumes are in a CG, then we make sure all volumes in the
        // CG and only the volumes in the CG are passed.
        URI cgURI = volume.getConsistencyGroup();
        if ((cg == null) && (!foundVolumeNotInCG)) {
            if (!isNullURI(cgURI)) {
                cg = _permissionsHelper.getObjectById(cgURI, BlockConsistencyGroup.class);
                _log.info("All volumes should be in CG {}:{}", cgURI, cg.getLabel());
                cgVolumes.addAll(blockServiceAPI.getActiveCGVolumes(cg));
            } else {
                _log.info("No volumes should be in CGs");
                foundVolumeNotInCG = true;
            }
        } else if (((cg != null) && (isNullURI(cgURI))) || ((foundVolumeNotInCG) && (!isNullURI(cgURI)))) {
            // A volume was in a CG, so all volumes must be in a CG.
            if (cg != null) {
                // Volumes should all be in the CG and this one is not.
                _log.error("Volume {}:{} is not in the CG", volumeURI, volume.getLabel());
            } else {
                _log.error("Volume {}:{} is in CG {}", new Object[] { volumeURI, volume.getLabel(), cgURI });
            }
            throw APIException.badRequests.mixedVolumesinCGForVarrayChange();
        }
        // Add the volume to the list
        volumes.add(volume);
    }
    // all in the same CG and all volumes are passed.
    if (cg != null) {
        // all volume in CG must have been passed.
        _log.info("Verify all volumes in CG {}:{}", cg.getId(), cg.getLabel());
        URI storageId = cg.getStorageController();
        if (!NullColumnValueGetter.isNullURI(storageId)) {
            StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageId);
            if (DiscoveredDataObject.Type.vplex.name().equals(storage.getSystemType())) {
                // in the CG.
                if (!VPlexUtil.verifyVolumesInCG(volumes, cgVolumes, _dbClient)) {
                    throw APIException.badRequests.cantChangeVarrayNotAllCGVolumes();
                }
            } else {
                verifyVolumesInCG(volumes, cgVolumes);
            }
        } else {
            verifyVolumesInCG(volumes, cgVolumes);
        }
    }
    // task state to pending.
    for (Volume volume : volumes) {
        Operation op = _dbClient.createTaskOpStatus(Volume.class, volume.getId(), taskId, ResourceOperationTypeEnum.CHANGE_BLOCK_VOLUME_VARRAY);
        TaskResourceRep resourceTask = toTask(volume, taskId, op);
        taskList.addTask(resourceTask);
    }
    // Now execute the varray change for the volumes.
    if (cg != null) {
        try {
            // When the volumes are part of a CG, executed as a single workflow.
            blockServiceAPI.changeVirtualArrayForVolumes(volumes, cg, cgVolumes, tgtVarray, taskId);
            _log.info("Executed virtual array change for volumes");
        } catch (InternalException | APIException e) {
            // Fail all the tasks.
            String errorMsg = String.format("Volume virtual array change error: %s", e.getMessage());
            _log.error(errorMsg);
            for (TaskResourceRep resourceTask : taskList.getTaskList()) {
                resourceTask.setState(Operation.Status.error.name());
                resourceTask.setMessage(errorMsg);
                _dbClient.error(Volume.class, resourceTask.getResource().getId(), taskId, e);
            }
        } catch (Exception e) {
            // Fail all the tasks.
            String errorMsg = String.format("Volume virtual array change error: %s", e.getMessage());
            _log.error(errorMsg);
            for (TaskResourceRep resourceTask : taskList.getTaskList()) {
                resourceTask.setState(Operation.Status.error.name());
                resourceTask.setMessage(errorMsg);
                _dbClient.error(Volume.class, resourceTask.getResource().getId(), taskId, InternalServerErrorException.internalServerErrors.unexpectedErrorDuringVarrayChange(e));
            }
        }
    } else {
        // When the volumes are not in a CG, then execute as individual workflows.
        for (Volume volume : volumes) {
            try {
                blockServiceAPI.changeVirtualArrayForVolumes(Arrays.asList(volume), cg, cgVolumes, tgtVarray, taskId);
                _log.info("Executed virtual array change for volume {}", volume.getId());
            } catch (InternalException | APIException e) {
                String errorMsg = String.format("Volume virtual array change error: %s", e.getMessage());
                _log.error(errorMsg);
                for (TaskResourceRep resourceTask : taskList.getTaskList()) {
                    // Fail the correct task.
                    if (resourceTask.getResource().getId().equals(volume.getId())) {
                        resourceTask.setState(Operation.Status.error.name());
                        resourceTask.setMessage(errorMsg);
                        _dbClient.error(Volume.class, resourceTask.getResource().getId(), taskId, e);
                    }
                }
            } catch (Exception e) {
                // Fail all the tasks.
                String errorMsg = String.format("Volume virtual array change error: %s", e.getMessage());
                _log.error(errorMsg);
                for (TaskResourceRep resourceTask : taskList.getTaskList()) {
                    // Fail the correct task.
                    if (resourceTask.getResource().getId().equals(volume.getId())) {
                        resourceTask.setState(Operation.Status.error.name());
                        resourceTask.setMessage(errorMsg);
                        _dbClient.error(Volume.class, resourceTask.getResource().getId(), taskId, InternalServerErrorException.internalServerErrors.unexpectedErrorDuringVarrayChange(e));
                    }
                }
            }
        }
    }
    return taskList;
}
Also used : VirtualArray(com.emc.storageos.db.client.model.VirtualArray) TaskList(com.emc.storageos.model.TaskList) ArrayList(java.util.ArrayList) TaskResourceRep(com.emc.storageos.model.TaskResourceRep) Operation(com.emc.storageos.db.client.model.Operation) URI(java.net.URI) NullColumnValueGetter.isNullURI(com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) APIException(com.emc.storageos.svcs.errorhandling.resources.APIException) BadRequestException(com.emc.storageos.svcs.errorhandling.resources.BadRequestException) ServiceCodeException(com.emc.storageos.svcs.errorhandling.resources.ServiceCodeException) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) Project(com.emc.storageos.db.client.model.Project) APIException(com.emc.storageos.svcs.errorhandling.resources.APIException) MapVolume(com.emc.storageos.api.mapper.functions.MapVolume) Volume(com.emc.storageos.db.client.model.Volume) BlockObject(com.emc.storageos.db.client.model.BlockObject) DiscoveredDataObject(com.emc.storageos.db.client.model.DiscoveredDataObject) DataObject(com.emc.storageos.db.client.model.DataObject) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Aggregations

Volume (com.emc.storageos.db.client.model.Volume)5 NullColumnValueGetter.isNullURI (com.emc.storageos.db.client.util.NullColumnValueGetter.isNullURI)5 URI (java.net.URI)5 ArrayList (java.util.ArrayList)3 MapVolume (com.emc.storageos.api.mapper.functions.MapVolume)2 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)2 BlockConsistencyGroup (com.emc.storageos.db.client.model.BlockConsistencyGroup)2 Project (com.emc.storageos.db.client.model.Project)2 VirtualArray (com.emc.storageos.db.client.model.VirtualArray)2 TaskList (com.emc.storageos.model.TaskList)2 AlternateIdConstraint (com.emc.storageos.db.client.constraint.AlternateIdConstraint)1 Constraint (com.emc.storageos.db.client.constraint.Constraint)1 ContainmentConstraint (com.emc.storageos.db.client.constraint.ContainmentConstraint)1 ContainmentPrefixConstraint (com.emc.storageos.db.client.constraint.ContainmentPrefixConstraint)1 PrefixConstraint (com.emc.storageos.db.client.constraint.PrefixConstraint)1 BlockObject (com.emc.storageos.db.client.model.BlockObject)1 BlockSnapshotSession (com.emc.storageos.db.client.model.BlockSnapshotSession)1 DataObject (com.emc.storageos.db.client.model.DataObject)1 DiscoveredDataObject (com.emc.storageos.db.client.model.DiscoveredDataObject)1 Operation (com.emc.storageos.db.client.model.Operation)1