Search in sources :

Example 11 with VPlexController

use of com.emc.storageos.vplexcontroller.VPlexController in project coprhd-controller by CoprHD.

the class VPlexBlockServiceApiImpl method upgradeToDistributed.

/**
 * Upgrade a local VPLEX volume to a distributed VPLEX volume.
 *
 * @param vplexURI -- VPLEX System URI
 * @param vplexVolume -- VPlex volume (existing).
 * @param vpool -- Requested vpool.
 * @param taskId
 * @throws InternalException
 */
private void upgradeToDistributed(URI vplexURI, Volume vplexVolume, VirtualPool vpool, String transferSpeed, String taskId) throws InternalException {
    try {
        VirtualArray neighborhood = _dbClient.queryObject(VirtualArray.class, vplexVolume.getVirtualArray());
        Set<URI> vplexes = new HashSet<URI>();
        vplexes.add(vplexURI);
        if (null == vplexVolume.getAssociatedVolumes() || vplexVolume.getAssociatedVolumes().isEmpty()) {
            s_logger.error("VPLEX volume {} has no backend volumes.", vplexVolume.forDisplay());
            throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(vplexVolume.forDisplay());
        }
        Iterator<String> assocIter = vplexVolume.getAssociatedVolumes().iterator();
        URI existingVolumeURI = new URI(assocIter.next());
        Volume existingVolume = _dbClient.queryObject(Volume.class, existingVolumeURI);
        if (existingVolume == null || existingVolume.getInactive() == true) {
            throw new ServiceCodeException(ServiceCode.UNFORSEEN_ERROR, "Existing volume inactive", new Object[] {});
        }
        VirtualPoolCapabilityValuesWrapper cosCapabilities = new VirtualPoolCapabilityValuesWrapper();
        cosCapabilities.put(VirtualPoolCapabilityValuesWrapper.SIZE, getVolumeCapacity(existingVolume));
        cosCapabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, new Integer(1));
        cosCapabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, existingVolume.getThinlyProvisioned());
        // Get a recommendation.
        // Then create the volume.
        List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
        Volume createVolume = null;
        // Determine if the user requested a specific HA VirtualArray and an associated HA VirtualPool.
        VirtualArray requestedHaVarray = null;
        VirtualPool requestedHaVirtualPool = vpool;
        if (vpool.getHaVarrayVpoolMap() != null && !vpool.getHaVarrayVpoolMap().isEmpty()) {
            for (String haNH : vpool.getHaVarrayVpoolMap().keySet()) {
                if (haNH.equals(NullColumnValueGetter.getNullURI().toString())) {
                    continue;
                }
                requestedHaVarray = _dbClient.queryObject(VirtualArray.class, new URI(haNH));
                String haVirtualPool = vpool.getHaVarrayVpoolMap().get(haNH);
                if (haVirtualPool.equals(NullColumnValueGetter.getNullURI().toString())) {
                    continue;
                }
                requestedHaVirtualPool = _dbClient.queryObject(VirtualPool.class, new URI(haVirtualPool));
                break;
            }
        }
        // Get the recommendations and pick one.
        List<Recommendation> recommendations = getBlockScheduler().scheduleStorageForImport(neighborhood, vplexes, requestedHaVarray, requestedHaVirtualPool, cosCapabilities);
        if (recommendations.isEmpty()) {
            throw APIException.badRequests.noStorageFoundForVolumeMigration(requestedHaVirtualPool.getLabel(), requestedHaVarray.getLabel(), existingVolume.getId());
        }
        Recommendation recommendation = recommendations.get(0);
        VPlexRecommendation vplexRecommendation = (VPlexRecommendation) recommendation;
        if (false == vplexURI.equals(vplexRecommendation.getVPlexStorageSystem())) {
            APIException.badRequests.vplexPlacementError(vplexVolume.getId());
        }
        StorageSystem vplexSystem = _dbClient.queryObject(StorageSystem.class, vplexURI);
        Project vplexProject = getVplexProject(vplexSystem, _dbClient, _tenantsService);
        // Prepare the created volume.
        VirtualArray haVirtualArray = _dbClient.queryObject(VirtualArray.class, vplexRecommendation.getVirtualArray());
        createVolume = prepareVolumeForRequest(getVolumeCapacity(existingVolume), vplexProject, haVirtualArray, requestedHaVirtualPool, vplexRecommendation.getSourceStorageSystem(), vplexRecommendation.getSourceStoragePool(), vplexVolume.getLabel() + "-1", ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME, taskId, _dbClient);
        createVolume.addInternalFlags(Flag.INTERNAL_OBJECT);
        _dbClient.updateObject(createVolume);
        VolumeDescriptor desc = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, createVolume.getStorageController(), createVolume.getId(), createVolume.getPool(), cosCapabilities);
        descriptors.add(desc);
        // Add a descriptor for the VPlex Virtual Volume.
        desc = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_VIRT_VOLUME, vplexVolume.getStorageController(), vplexVolume.getId(), vplexVolume.getPool(), cosCapabilities);
        descriptors.add(desc);
        // Now send the command to the controller.
        try {
            s_logger.info("Calling VPlex controller.");
            VPlexController controller = getController();
            controller.importVolume(vplexURI, descriptors, null, null, vpool.getId(), null, transferSpeed, Boolean.TRUE, taskId);
        // controller.importVolume(vplexURI, vpool.getId(),
        // null, null, /* no need to pass System Project/Tenant */
        // null, /* no import volume */
        // createVolume.getId(), vplexVolume.getId(), taskId);
        } catch (InternalException ex) {
            s_logger.error("ControllerException on upgradeToDistributed", ex);
            String errMsg = String.format("ControllerException: %s", ex.getMessage());
            Operation statusUpdate = new Operation(Operation.Status.error.name(), errMsg);
            _dbClient.updateTaskOpStatus(Volume.class, vplexVolume.getId(), taskId, statusUpdate);
            throw ex;
        }
    } catch (URISyntaxException ex) {
        s_logger.debug("URISyntaxException", ex);
    }
}
Also used : VirtualPoolCapabilityValuesWrapper(com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper) VirtualArray(com.emc.storageos.db.client.model.VirtualArray) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) VPlexRecommendation(com.emc.storageos.volumecontroller.VPlexRecommendation) VPlexController(com.emc.storageos.vplexcontroller.VPlexController) ServiceCodeException(com.emc.storageos.svcs.errorhandling.resources.ServiceCodeException) ArrayList(java.util.ArrayList) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) Operation(com.emc.storageos.db.client.model.Operation) URISyntaxException(java.net.URISyntaxException) FCTN_STRING_TO_URI(com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_STRING_TO_URI) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) FCTN_VPLEX_MIRROR_TO_URI(com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_VPLEX_MIRROR_TO_URI) SRDFCopyRecommendation(com.emc.storageos.volumecontroller.SRDFCopyRecommendation) VolumeRecommendation(com.emc.storageos.api.service.impl.placement.VolumeRecommendation) VPlexRecommendation(com.emc.storageos.volumecontroller.VPlexRecommendation) Recommendation(com.emc.storageos.volumecontroller.Recommendation) SRDFRecommendation(com.emc.storageos.volumecontroller.SRDFRecommendation) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) Project(com.emc.storageos.db.client.model.Project) Volume(com.emc.storageos.db.client.model.Volume) HashSet(java.util.HashSet) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 12 with VPlexController

use of com.emc.storageos.vplexcontroller.VPlexController in project coprhd-controller by CoprHD.

the class VPlexBlockServiceApiImpl method startNativeContinuousCopies.

/**
 * {@inheritDoc}
 */
@Override
public TaskList startNativeContinuousCopies(StorageSystem vplexStorageSystem, Volume vplexVolume, VirtualPool sourceVirtualPool, VirtualPoolCapabilityValuesWrapper capabilities, NativeContinuousCopyCreate param, String taskId) throws ControllerException {
    // using the target volume of a block snapshot.
    if (VPlexUtil.isVolumeBuiltOnBlockSnapshot(_dbClient, vplexVolume)) {
        throw APIException.badRequests.mirrorNotAllowedVolumeIsExposedSnapshot(vplexVolume.getId().toString());
    }
    validateNotAConsistencyGroupVolume(vplexVolume, sourceVirtualPool);
    TaskList taskList = new TaskList();
    // Currently, For Vplex Local Volume this will create a single mirror and add it
    // to the vplex volume. For Vplex Distributed Volume this will create single mirror
    // on source and/or HA side and add it to the vplex volume. Two steps: first place
    // the mirror and then prepare the mirror.
    URI vplexStorageSystemURI = vplexVolume.getStorageController();
    // For VPLEX Local volume there will be only one associated volume entry in this set.
    StringSet associatedVolumeIds = vplexVolume.getAssociatedVolumes();
    if (associatedVolumeIds == null) {
        throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(vplexVolume.forDisplay());
    }
    VirtualPool sourceMirrorVPool = null;
    // Set source mirror vpool
    if (!isNullOrEmpty(sourceVirtualPool.getMirrorVirtualPool()) && !NullColumnValueGetter.isNullURI(URI.create(sourceVirtualPool.getMirrorVirtualPool()))) {
        sourceMirrorVPool = _dbClient.queryObject(VirtualPool.class, URI.create(sourceVirtualPool.getMirrorVirtualPool()));
    }
    // Check if volume is distributed and if HA Mirror Vpool is also set
    VirtualPool haMirrorVPool = VPlexUtil.getHAMirrorVpool(sourceVirtualPool, associatedVolumeIds, _dbClient);
    // Map of backend volume and the mirror pool to target backend volume for the mirror
    Map<Volume, VirtualPool> backendVolumeToMirrorVpoolMap = new HashMap<Volume, VirtualPool>();
    if (associatedVolumeIds.size() > 1) {
        // If associatedVolumeIds size is greater than 1 then its a VPLEX Distributed Volume
        updateBackendVolumeToMirrorVpoolMap(vplexVolume, associatedVolumeIds, sourceVirtualPool, sourceMirrorVPool, haMirrorVPool, backendVolumeToMirrorVpoolMap);
    } else {
        // If we are here that means we need to create mirror for the VPLEX local volume
        for (String associatedVolumeId : associatedVolumeIds) {
            Volume associatedVolume = _dbClient.queryObject(Volume.class, URI.create(associatedVolumeId));
            if (associatedVolume != null) {
                backendVolumeToMirrorVpoolMap.put(associatedVolume, sourceMirrorVPool);
            }
        }
    }
    // Project is not passed in continuous copies call.
    // Implicit assumption to use same project as the source volume.
    Project project = _permissionsHelper.getObjectById(vplexVolume.getProject(), Project.class);
    Map<Volume, List<Recommendation>> backendvolumeToMirrorRecommendationMap = new HashMap<Volume, List<Recommendation>>();
    Map<Volume, VirtualArray> backendvolumeToMirrorVarrayMap = new HashMap<Volume, VirtualArray>();
    for (Volume backendVolume : backendVolumeToMirrorVpoolMap.keySet()) {
        URI backendVolumeVarrayURI = backendVolume.getVirtualArray();
        // Get the VPLEX cluster value from the varray
        String cluster = ConnectivityUtil.getVplexClusterForVarray(backendVolumeVarrayURI, vplexStorageSystemURI, _dbClient);
        if (cluster.equals(ConnectivityUtil.CLUSTER_UNKNOWN)) {
            throw InternalServerErrorException.internalServerErrors.noVplexClusterInfoForVarray(backendVolumeVarrayURI.toString(), vplexStorageSystemURI.toString());
        }
        VirtualPool backendVolumeVpool = _dbClient.queryObject(VirtualPool.class, backendVolume.getVirtualPool());
        VirtualPool mirrorVpool = backendVolumeToMirrorVpoolMap.get(backendVolume);
        // Get recommendations for the mirror placement
        List<Recommendation> volumeRecommendations = null;
        VirtualArray varray = null;
        if (mirrorVpool != null) {
            // If mirror vpool is provided try to get recommendations using the provided mirror vpool
            // Check if any of the varray for mirror vpool is same as that of the source volume varray.
            // If yes then get recommendations using that varray.
            StringSet mirrorVPoolVarrays = mirrorVpool.getVirtualArrays();
            boolean foundMatch = false;
            for (String mirrorVPoolVarrayId : mirrorVPoolVarrays) {
                if (mirrorVPoolVarrayId.equals(backendVolumeVarrayURI.toString())) {
                    varray = _dbClient.queryObject(VirtualArray.class, backendVolumeVarrayURI);
                    volumeRecommendations = _scheduler.getRecommendationsForMirrors(varray, project, backendVolumeVpool, mirrorVpool, capabilities, vplexStorageSystemURI, backendVolume.getStorageController(), cluster);
                    foundMatch = true;
                    break;
                }
            }
            if (!foundMatch) {
                s_logger.info("Mirror Vpool varray is different than the source vpool varray");
                // with the source volume VPLEX system.
                for (String mirrorVPoolVarrayId : mirrorVPoolVarrays) {
                    if (VPlexUtil.checkIfVarrayContainsSpecifiedVplexSystem(mirrorVPoolVarrayId, cluster, vplexStorageSystemURI, _dbClient)) {
                        varray = _dbClient.queryObject(VirtualArray.class, URI.create(mirrorVPoolVarrayId));
                        volumeRecommendations = _scheduler.getRecommendationsForMirrors(varray, project, backendVolumeVpool, mirrorVpool, capabilities, vplexStorageSystemURI, backendVolume.getStorageController(), cluster);
                        if (!volumeRecommendations.isEmpty()) {
                            foundMatch = true;
                            break;
                        } else {
                            s_logger.info("Tried to get recommemdations using varray {} {}. ", varray.getId(), varray.getLabel());
                        }
                    }
                }
            }
        } else {
            if (sourceVirtualPool.getHighAvailability().equals(VirtualPool.HighAvailabilityType.vplex_local.name())) {
                s_logger.info("Mirror vpool is not specified, use the source volume virtual pool and virtual array");
                // In case of Vplex local if mirror pool is not provided then we can use source vpool as mirror vpool.
                sourceMirrorVPool = backendVolumeVpool;
                mirrorVpool = backendVolumeVpool;
                backendVolumeToMirrorVpoolMap.put(backendVolume, sourceMirrorVPool);
                // Separate Mirror vpool is not provided so use the source volume vpool and varray for
                // getting recommendations.Here sourceVirtualPool and mirrorVPool will be same.
                varray = _dbClient.queryObject(VirtualArray.class, backendVolumeVarrayURI);
                volumeRecommendations = _scheduler.getRecommendationsForMirrors(varray, project, backendVolumeVpool, mirrorVpool, capabilities, vplexStorageSystemURI, backendVolume.getStorageController(), cluster);
            }
        }
        if (mirrorVpool == null) {
            throw APIException.badRequests.noMirrorVpoolForVplexVolume(vplexVolume.getLabel());
        }
        if (varray == null) {
            throw APIException.badRequests.noVarrayForMirrorVpoolWithExpectedVplex(mirrorVpool.getLabel(), vplexStorageSystem.getLabel(), cluster);
        }
        if (volumeRecommendations == null || volumeRecommendations.isEmpty()) {
            if (volumeRecommendations.isEmpty()) {
                StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, backendVolume.getStorageController());
                throw APIException.badRequests.noMatchingStoragePoolsForContinuousCopiesVpoolForVplex(varray.getLabel(), sourceMirrorVPool.getLabel(), storageSystem.getLabel());
            }
        }
        // Add mirror recommendations for the backend volume to the map
        backendvolumeToMirrorRecommendationMap.put(backendVolume, volumeRecommendations);
        backendvolumeToMirrorVarrayMap.put(backendVolume, varray);
    }
    // Prepare mirror.
    int varrayCount = 0;
    int volumeCounter = 1;
    // volumeCount will be always 1 for now
    int volumeCount = capabilities.getResourceCount();
    String volumeLabel = param.getName();
    List<URI> allVolumes = new ArrayList<URI>();
    List<URI> allMirrors = new ArrayList<URI>();
    List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
    // Currently only one local mirror is supported for the VPLEX local virtual volume
    List<VplexMirror> preparedMirrors = new ArrayList<VplexMirror>();
    for (Volume backendVolume : backendvolumeToMirrorRecommendationMap.keySet()) {
        List<Recommendation> volumeRecommendations = backendvolumeToMirrorRecommendationMap.get(backendVolume);
        VirtualArray varray = backendvolumeToMirrorVarrayMap.get(backendVolume);
        VirtualPool mirrorVpool = backendVolumeToMirrorVpoolMap.get(backendVolume);
        long thinVolumePreAllocationSize = 0;
        if (null != mirrorVpool.getThinVolumePreAllocationPercentage()) {
            thinVolumePreAllocationSize = VirtualPoolUtil.getThinVolumePreAllocationSize(mirrorVpool.getThinVolumePreAllocationPercentage(), vplexVolume.getCapacity());
        }
        for (Recommendation volumeRecommendation : volumeRecommendations) {
            VPlexRecommendation vplexRecommendation = (VPlexRecommendation) volumeRecommendation;
            StringBuilder mirrorLabelBuilder = new StringBuilder(volumeLabel);
            if (backendVolume.getVirtualArray().equals(vplexVolume.getVirtualArray())) {
                varrayCount = 0;
            } else {
                varrayCount = 1;
            }
            mirrorLabelBuilder.append('-').append(varrayCount);
            if (volumeCount > 1) {
                mirrorLabelBuilder.append('-').append(volumeCounter++);
            }
            // Create mirror object
            VplexMirror createdMirror = initializeMirror(vplexVolume, mirrorVpool, varray, mirrorLabelBuilder.toString(), thinVolumePreAllocationSize, _dbClient);
            preparedMirrors.add(createdMirror);
            Operation op = _dbClient.createTaskOpStatus(VplexMirror.class, createdMirror.getId(), taskId, ResourceOperationTypeEnum.ATTACH_VPLEX_LOCAL_MIRROR);
            s_logger.info("Prepared mirror {}", createdMirror.getId());
            allMirrors.add(createdMirror.getId());
            // Add descriptor for the mirror.
            VolumeDescriptor descriptor = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_LOCAL_MIRROR, vplexStorageSystemURI, createdMirror.getId(), null, capabilities);
            descriptors.add(descriptor);
            // Create backend volume object and add it to the VplexMirror created above.
            Volume volume = prepareVolume(createdMirror, backendVolume, mirrorVpool, varray, vplexRecommendation.getSourceStorageSystem(), vplexRecommendation.getSourceStoragePool(), mirrorLabelBuilder.toString(), thinVolumePreAllocationSize, capabilities, _dbClient);
            op = new Operation();
            op.setResourceType(ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME);
            _dbClient.createTaskOpStatus(Volume.class, volume.getId(), taskId, op);
            URI volumeId = volume.getId();
            allVolumes.add(volumeId);
            s_logger.info("Prepared volume {}", volumeId);
            // Add descriptor for the backend volume
            descriptor = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, vplexRecommendation.getSourceStorageSystem(), volumeId, vplexRecommendation.getSourceStoragePool(), capabilities);
            descriptors.add(descriptor);
        }
    }
    Collection<URI> mirrorTargetIds = Collections2.transform(preparedMirrors, FCTN_VPLEX_MIRROR_TO_URI);
    String mirrorTargetCommaDelimList = Joiner.on(',').join(mirrorTargetIds);
    Operation op = _dbClient.createTaskOpStatus(Volume.class, vplexVolume.getId(), taskId, ResourceOperationTypeEnum.ATTACH_VPLEX_LOCAL_MIRROR, mirrorTargetCommaDelimList);
    taskList.getTaskList().add(toTask(vplexVolume, preparedMirrors, taskId, op));
    try {
        VPlexController controller = getController();
        controller.attachContinuousCopies(vplexStorageSystem.getId(), descriptors, vplexVolume.getId(), taskId);
    } catch (InternalException e) {
        if (s_logger.isErrorEnabled()) {
            s_logger.error("Controller error", e);
        }
        String errMsg = String.format("Controller error: %s", e.getMessage());
        for (URI volumeURI : allVolumes) {
            _dbClient.error(Volume.class, volumeURI, taskId, e);
        }
        for (URI mirrorURI : allMirrors) {
            _dbClient.error(VplexMirror.class, mirrorURI, taskId, e);
        }
        for (TaskResourceRep volumeTask : taskList.getTaskList()) {
            volumeTask.setState(Operation.Status.error.name());
            volumeTask.setMessage(errMsg);
        }
        throw e;
    }
    return taskList;
}
Also used : VirtualArray(com.emc.storageos.db.client.model.VirtualArray) VPlexController(com.emc.storageos.vplexcontroller.VPlexController) HashMap(java.util.HashMap) TaskList(com.emc.storageos.model.TaskList) ArrayList(java.util.ArrayList) Operation(com.emc.storageos.db.client.model.Operation) FCTN_STRING_TO_URI(com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_STRING_TO_URI) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) FCTN_VPLEX_MIRROR_TO_URI(com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_VPLEX_MIRROR_TO_URI) StringSet(com.emc.storageos.db.client.model.StringSet) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) TaskList(com.emc.storageos.model.TaskList) VolumeGroupVolumeList(com.emc.storageos.model.application.VolumeGroupUpdateParam.VolumeGroupVolumeList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) StorageSystemConnectivityList(com.emc.storageos.model.systems.StorageSystemConnectivityList) List(java.util.List) VplexMirror(com.emc.storageos.db.client.model.VplexMirror) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) VPlexRecommendation(com.emc.storageos.volumecontroller.VPlexRecommendation) TaskResourceRep(com.emc.storageos.model.TaskResourceRep) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) SRDFCopyRecommendation(com.emc.storageos.volumecontroller.SRDFCopyRecommendation) VolumeRecommendation(com.emc.storageos.api.service.impl.placement.VolumeRecommendation) VPlexRecommendation(com.emc.storageos.volumecontroller.VPlexRecommendation) Recommendation(com.emc.storageos.volumecontroller.Recommendation) SRDFRecommendation(com.emc.storageos.volumecontroller.SRDFRecommendation) 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) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) Project(com.emc.storageos.db.client.model.Project) Volume(com.emc.storageos.db.client.model.Volume)

Example 13 with VPlexController

use of com.emc.storageos.vplexcontroller.VPlexController in project coprhd-controller by CoprHD.

the class VPlexBlockServiceApiImpl method resynchronizeSnapshot.

/**
 * {@inheritDoc}
 */
@Override
public void resynchronizeSnapshot(BlockSnapshot snapshot, Volume parentVolume, String taskId) {
    VPlexController controller = getController();
    Volume vplexVolume = Volume.fetchVplexVolume(_dbClient, parentVolume);
    StorageSystem vplexSystem = _dbClient.queryObject(StorageSystem.class, vplexVolume.getStorageController());
    controller.resyncSnapshot(vplexSystem.getId(), snapshot.getId(), taskId);
}
Also used : VPlexController(com.emc.storageos.vplexcontroller.VPlexController) Volume(com.emc.storageos.db.client.model.Volume) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 14 with VPlexController

use of com.emc.storageos.vplexcontroller.VPlexController in project coprhd-controller by CoprHD.

the class VPlexBlockServiceApiImpl method deactivateMirror.

/**
 * {@inheritDoc}
 */
@Override
public TaskList deactivateMirror(StorageSystem vplexStorageSystem, URI mirrorURI, String taskId, String deleteType) {
    TaskList taskList = new TaskList();
    try {
        VplexMirror mirror = _dbClient.queryObject(VplexMirror.class, mirrorURI);
        Volume sourceVolume = _dbClient.queryObject(Volume.class, mirror.getSource().getURI());
        Operation op = _dbClient.createTaskOpStatus(Volume.class, sourceVolume.getId(), taskId, ResourceOperationTypeEnum.DEACTIVATE_VOLUME_MIRROR, mirror.getId().toString());
        taskList.getTaskList().add(toTask(sourceVolume, Arrays.asList(mirror), taskId, op));
        if (VolumeDeleteTypeEnum.VIPR_ONLY.name().equals(deleteType)) {
            s_logger.info("Perform ViPR-only delete for VPLEX mirrors %s", mirrorURI);
            // Perform any database cleanup that is required.
            cleanupForViPROnlyMirrorDelete(Arrays.asList(mirrorURI));
            // Mark them inactive.
            _dbClient.markForDeletion(_dbClient.queryObject(VplexMirror.class, mirrorURI));
            // We must get the volume from the DB again, to properly update the status.
            sourceVolume = _dbClient.queryObject(Volume.class, mirror.getSource().getURI());
            op = sourceVolume.getOpStatus().get(taskId);
            op.ready("VPLEX continuous copy succesfully deleted from ViPR");
            sourceVolume.getOpStatus().updateTaskStatus(taskId, op);
            _dbClient.updateObject(sourceVolume);
        } else {
            List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
            // Add a descriptor for each of the associated volumes.There will be only one associated volume
            if (mirror.getAssociatedVolumes() != null) {
                for (String assocVolId : mirror.getAssociatedVolumes()) {
                    Volume assocVolume = _dbClient.queryObject(Volume.class, URI.create(assocVolId));
                    if (assocVolume != null && !assocVolume.getInactive() && assocVolume.getNativeId() != null) {
                        // In order to add descriptor for the the backend volumes that needs to be
                        // deleted we are checking for volume nativeId as well, because its possible
                        // that we were not able to create backend volume due to SMIS communication
                        // and rollback didn't clean up VplexMirror and its associated volumes in
                        // database. So in such a case nativeId will be null and we just want to skip
                        // sending this volume to SMIS, else it fails with null reference when user
                        // attempts to cleanup this failed mirror.
                        VolumeDescriptor assocDesc = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, assocVolume.getStorageController(), assocVolume.getId(), null, null);
                        descriptors.add(assocDesc);
                    }
                }
            }
            VPlexController controller = getController();
            controller.deactivateMirror(vplexStorageSystem.getId(), mirror.getId(), descriptors, taskId);
        }
    } catch (ControllerException e) {
        String errorMsg = format("Failed to deactivate continuous copy %s: %s", mirrorURI.toString(), e.getMessage());
        s_logger.error(errorMsg, e);
        for (TaskResourceRep taskResourceRep : taskList.getTaskList()) {
            taskResourceRep.setState(Operation.Status.error.name());
            taskResourceRep.setMessage(errorMsg);
            _dbClient.error(Volume.class, taskResourceRep.getResource().getId(), taskId, e);
        }
    } catch (Exception e) {
        String errorMsg = format("Failed to deactivate continuous copy %s: %s", mirrorURI.toString(), e.getMessage());
        s_logger.error(errorMsg, e);
        ServiceCoded sc = APIException.internalServerErrors.genericApisvcError(errorMsg, e);
        for (TaskResourceRep taskResourceRep : taskList.getTaskList()) {
            taskResourceRep.setState(Operation.Status.error.name());
            taskResourceRep.setMessage(sc.getMessage());
            _dbClient.error(Volume.class, taskResourceRep.getResource().getId(), taskId, sc);
        }
    }
    return taskList;
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) VPlexController(com.emc.storageos.vplexcontroller.VPlexController) ControllerException(com.emc.storageos.volumecontroller.ControllerException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) TaskList(com.emc.storageos.model.TaskList) ArrayList(java.util.ArrayList) TaskResourceRep(com.emc.storageos.model.TaskResourceRep) Operation(com.emc.storageos.db.client.model.Operation) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) URISyntaxException(java.net.URISyntaxException) APIException(com.emc.storageos.svcs.errorhandling.resources.APIException) BadRequestException(com.emc.storageos.svcs.errorhandling.resources.BadRequestException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ServiceCodeException(com.emc.storageos.svcs.errorhandling.resources.ServiceCodeException) Volume(com.emc.storageos.db.client.model.Volume) ServiceCoded(com.emc.storageos.svcs.errorhandling.model.ServiceCoded) VplexMirror(com.emc.storageos.db.client.model.VplexMirror)

Example 15 with VPlexController

use of com.emc.storageos.vplexcontroller.VPlexController in project coprhd-controller by CoprHD.

the class MigrationService method migrateVolume.

/**
 * Performs a non-disruptive migration for the passed VPLEX virtual volume.
 * The backend volume of the VPLEX volume that is migrated is the backend
 * volume on the passed source storage system. The volume is migrated to the
 * passed target storage system, which must be connected to the same VPLEX
 * cluster as the source storage system.
 *
 * @prereq none
 *
 * @param migrateParam A reference to the migration parameters.
 * @deprecated Use the Change Virtual Pool API instead
 * @brief Perform a non-disruptive migration for a VPLEX volume.
 * @return A TaskResourceRep for the volume being migrated.
 * @throws InternalException
 */
@Deprecated
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_ADMIN })
public TaskResourceRep migrateVolume(MigrationParam migrateParam) throws InternalException {
    // Create a unique task id.
    String taskId = UUID.randomUUID().toString();
    s_logger.info("Migrate volume {} from storage system {} to storage system {}", new Object[] { migrateParam.getVolume(), migrateParam.getSrcStorageSystem(), migrateParam.getTgtStorageSystem() });
    // Verify the requested volume supports migration.
    Volume vplexVolume = verifyRequestedVolumeSupportsMigration(migrateParam.getVolume());
    s_logger.debug("Verfified requested volume");
    // Make sure that we don't have some pending
    // operation against the volume
    checkForPendingTasks(Arrays.asList(vplexVolume.getTenant().getURI()), Arrays.asList(vplexVolume));
    // Determine the backend volume of the requested VPlex volume that
    // is to be migrated. It is the volume on the passed source storage
    // system.
    Volume migrationSrc = getMigrationSource(vplexVolume, migrateParam.getSrcStorageSystem());
    s_logger.debug("Migration source is {}", migrationSrc.getId());
    // The project for the migration target will be the same as that
    // of the source.
    Project migrationTgtProject = _permissionsHelper.getObjectById(migrationSrc.getProject().getURI(), Project.class);
    s_logger.debug("Migration target project is {}", migrationTgtProject.getId());
    // The VirtualArray for the migration target will be the same as
    // that of the source.
    VirtualArray migrationTargetVarray = _permissionsHelper.getObjectById(migrationSrc.getVirtualArray(), VirtualArray.class);
    s_logger.debug("Migration target VirtualArray is {}", migrationTargetVarray.getId());
    // Verify the requested target storage system exists and
    // is a system to which the migration source volume can
    // be migrated.
    verifyTargetStorageSystemForMigration(migrateParam.getVolume(), vplexVolume.getStorageController(), migrateParam.getSrcStorageSystem(), migrateParam.getTgtStorageSystem());
    s_logger.debug("Verified target storage system {}", migrateParam.getTgtStorageSystem());
    // Get the VirtualPool for the migration target.
    VirtualPool migrationTgtCos = getVirtualPoolForMigrationTarget(migrateParam.getVirtualPool(), vplexVolume, migrationSrc);
    s_logger.debug("Migration target VirtualPool is {}", migrationTgtCos.getId());
    // Get the VPlex storage system for the virtual volume.
    URI vplexSystemURI = vplexVolume.getStorageController();
    Set<URI> requestedVPlexSystems = new HashSet<URI>();
    requestedVPlexSystems.add(vplexSystemURI);
    // Get a placement recommendation on the requested target storage
    // system connected to the VPlex storage system of the VPlex volume.
    VPlexScheduler vplexScheduler = _vplexBlockServiceApi.getBlockScheduler();
    VirtualPoolCapabilityValuesWrapper cosWrapper = new VirtualPoolCapabilityValuesWrapper();
    cosWrapper.put(VirtualPoolCapabilityValuesWrapper.SIZE, migrationSrc.getCapacity());
    cosWrapper.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, new Integer(1));
    List<Recommendation> recommendations = vplexScheduler.scheduleStorage(migrationTargetVarray, requestedVPlexSystems, migrateParam.getTgtStorageSystem(), migrationTgtCos, false, null, null, cosWrapper, migrationTgtProject, VpoolUse.ROOT, new HashMap<VpoolUse, List<Recommendation>>());
    if (recommendations.isEmpty()) {
        throw APIException.badRequests.noStorageFoundForVolumeMigration(migrationTgtCos.getLabel(), migrationTargetVarray.getLabel(), vplexVolume.getId());
    }
    s_logger.debug("Got recommendation for migration target");
    // There should be a single recommendation.
    Recommendation recommendation = recommendations.get(0);
    URI recommendedSystem = recommendation.getSourceStorageSystem();
    URI recommendedPool = recommendation.getSourceStoragePool();
    s_logger.debug("Recommendation storage system is {}", recommendedSystem);
    s_logger.debug("Recommendation storage pool is {}", recommendedPool);
    // Prepare the migration target.
    List<URI> migrationTgts = new ArrayList<URI>();
    Map<URI, URI> poolTgtMap = new HashMap<URI, URI>();
    Long size = _vplexBlockServiceApi.getVolumeCapacity(migrationSrc);
    Volume migrationTgt = VPlexBlockServiceApiImpl.prepareVolumeForRequest(size, migrationTgtProject, migrationTargetVarray, migrationTgtCos, recommendedSystem, recommendedPool, migrationSrc.getLabel(), ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME, taskId, _dbClient);
    URI migrationTgtURI = migrationTgt.getId();
    migrationTgts.add(migrationTgtURI);
    poolTgtMap.put(recommendedPool, migrationTgtURI);
    s_logger.debug("Prepared migration target volume {}", migrationTgtURI);
    // Prepare the migration.
    Map<URI, URI> migrationsMap = new HashMap<URI, URI>();
    Migration migration = _vplexBlockServiceApi.prepareMigration(migrateParam.getVolume(), migrationSrc.getId(), migrationTgt.getId(), taskId);
    migrationsMap.put(migrationTgtURI, migration.getId());
    s_logger.debug("Prepared migration {}", migration.getId());
    // Create a task for the virtual volume being migrated and set the
    // initial task state to pending.
    Operation op = _dbClient.createTaskOpStatus(Volume.class, vplexVolume.getId(), taskId, ResourceOperationTypeEnum.MIGRATE_BLOCK_VOLUME);
    TaskResourceRep task = toTask(vplexVolume, taskId, op);
    s_logger.debug("Created task for volume {}", migrateParam.getVolume());
    try {
        VPlexController controller = _vplexBlockServiceApi.getController();
        String successMsg = String.format("Migration succeeded for volume %s", migrateParam.getVolume());
        String failMsg = String.format("Migration failed for volume %s", migrateParam.getVolume());
        controller.migrateVolumes(vplexSystemURI, migrateParam.getVolume(), migrationTgts, migrationsMap, poolTgtMap, (migrateParam.getVirtualPool() != null ? migrateParam.getVirtualPool() : null), null, successMsg, failMsg, null, taskId, null);
        s_logger.debug("Got VPlex controller and created migration workflow");
    } catch (InternalException e) {
        s_logger.error("Controller Error", e);
        String errMsg = String.format("Controller Error: %s", e.getMessage());
        task.setState(Operation.Status.error.name());
        task.setMessage(errMsg);
        Operation opStatus = new Operation(Operation.Status.error.name(), errMsg);
        _dbClient.updateTaskOpStatus(Volume.class, task.getResource().getId(), taskId, opStatus);
        migrationTgt.setInactive(true);
        _dbClient.persistObject(migrationTgt);
        migration.setInactive(true);
        _dbClient.persistObject(migration);
        throw e;
    }
    return task;
}
Also used : VirtualPoolCapabilityValuesWrapper(com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper) VirtualArray(com.emc.storageos.db.client.model.VirtualArray) VPlexController(com.emc.storageos.vplexcontroller.VPlexController) HashMap(java.util.HashMap) Migration(com.emc.storageos.db.client.model.Migration) ArrayList(java.util.ArrayList) Operation(com.emc.storageos.db.client.model.Operation) URI(java.net.URI) List(java.util.List) ArrayList(java.util.ArrayList) BulkList(com.emc.storageos.api.service.impl.response.BulkList) MigrationList(com.emc.storageos.model.block.MigrationList) HashSet(java.util.HashSet) VpoolUse(com.emc.storageos.api.service.impl.placement.VpoolUse) TaskResourceRep(com.emc.storageos.model.TaskResourceRep) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) Recommendation(com.emc.storageos.volumecontroller.Recommendation) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) Project(com.emc.storageos.db.client.model.Project) Volume(com.emc.storageos.db.client.model.Volume) VPlexScheduler(com.emc.storageos.api.service.impl.placement.VPlexScheduler) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) CheckPermission(com.emc.storageos.security.authorization.CheckPermission)

Aggregations

VPlexController (com.emc.storageos.vplexcontroller.VPlexController)20 Volume (com.emc.storageos.db.client.model.Volume)17 URI (java.net.URI)17 Operation (com.emc.storageos.db.client.model.Operation)16 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)13 TaskResourceRep (com.emc.storageos.model.TaskResourceRep)11 ArrayList (java.util.ArrayList)10 NamedURI (com.emc.storageos.db.client.model.NamedURI)9 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)9 FCTN_STRING_TO_URI (com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_STRING_TO_URI)7 FCTN_VPLEX_MIRROR_TO_URI (com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_VPLEX_MIRROR_TO_URI)7 VirtualPool (com.emc.storageos.db.client.model.VirtualPool)6 TaskList (com.emc.storageos.model.TaskList)6 VolumeDescriptor (com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor)5 Migration (com.emc.storageos.db.client.model.Migration)5 VirtualArray (com.emc.storageos.db.client.model.VirtualArray)5 CheckPermission (com.emc.storageos.security.authorization.CheckPermission)5 POST (javax.ws.rs.POST)5 Produces (javax.ws.rs.Produces)5 Project (com.emc.storageos.db.client.model.Project)4