Search in sources :

Example 1 with VolumeVpoolChangeTaskCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter in project coprhd-controller by CoprHD.

the class RPDeviceController method updateConsistencyGroupPolicy.

@Override
public void updateConsistencyGroupPolicy(URI protectionDevice, URI consistencyGroup, List<URI> volumeURIs, URI newVpoolURI, String task) throws InternalException {
    _log.info(String.format("Request to update consistency group policy for volumes %s through virtual pool change to %s", volumeURIs, newVpoolURI));
    VolumeVpoolChangeTaskCompleter taskCompleter = null;
    URI oldVpoolURI = null;
    List<Volume> volumes = new ArrayList<Volume>();
    List<Volume> vplexBackendVolumes = new ArrayList<Volume>();
    try {
        // Get all CG source volumes. The entire CG policy is being updated so we
        // need to capture the existing vpools for all the source volumes before
        // changing them.
        List<Volume> cgVolumes = RPHelper.getCgSourceVolumes(consistencyGroup, _dbClient);
        VirtualPool newVpool = _dbClient.queryObject(VirtualPool.class, newVpoolURI);
        Map<URI, URI> oldVpools = new HashMap<URI, URI>();
        for (Volume volume : cgVolumes) {
            // Save the old virtual pool
            oldVpoolURI = volume.getVirtualPool();
            oldVpools.put(volume.getId(), oldVpoolURI);
            // Update to the new virtual pool
            volume.setVirtualPool(newVpoolURI);
            volumes.add(volume);
            // If this is a VPlex volume, there will be
            StringSet associatedVolumeIds = volume.getAssociatedVolumes();
            // Perform additional tasks if this volume is a VPlex volume
            if (associatedVolumeIds != null && !associatedVolumeIds.isEmpty()) {
                Volume backendSrc = null;
                Volume backendHa = null;
                for (String associatedVolumeId : associatedVolumeIds) {
                    Volume associatedVolume = _dbClient.queryObject(Volume.class, URI.create(associatedVolumeId));
                    // Assign the associated volumes to either be the source or HA
                    if (associatedVolume != null) {
                        if (associatedVolume.getVirtualArray().equals(volume.getVirtualArray())) {
                            backendSrc = associatedVolume;
                        } else {
                            backendHa = associatedVolume;
                        }
                    }
                }
                if (backendSrc != null) {
                    // Change the back end volume's vPool too
                    backendSrc.setVirtualPool(newVpoolURI);
                    vplexBackendVolumes.add(backendSrc);
                    _log.info(String.format("Changing VirtualPool for VPLEX backend source volume %s (%s) from %s to %s", backendSrc.getLabel(), backendSrc.getId(), oldVpoolURI, newVpoolURI));
                    if (backendHa != null) {
                        VirtualPool newHAVpool = VirtualPool.getHAVPool(newVpool, _dbClient);
                        if (newHAVpool == null) {
                            // it may not be set
                            newHAVpool = newVpool;
                        }
                        backendHa.setVirtualPool(newHAVpool.getId());
                        vplexBackendVolumes.add(backendHa);
                    }
                }
            }
        }
        _dbClient.updateObject(volumes);
        _dbClient.updateObject(vplexBackendVolumes);
        // The VolumeVpoolChangeTaskCompleter will restore the old Virtual Pool
        taskCompleter = new VolumeVpoolChangeTaskCompleter(volumeURIs, oldVpools, task);
    } catch (Exception ex) {
        _log.error("Unexpected exception reading volume or generating taskCompleter: ", ex);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
        VolumeWorkflowCompleter completer = new VolumeWorkflowCompleter(volumeURIs, task);
        completer.error(_dbClient, serviceError);
    }
    try {
        Workflow workflow = _workflowService.getNewWorkflow(this, "updateReplicationMode", false, task);
        ProtectionSystem protectionSystem = _dbClient.queryObject(ProtectionSystem.class, protectionDevice);
        if (!volumes.isEmpty()) {
            VirtualPool newVirtualPool = _dbClient.queryObject(VirtualPool.class, newVpoolURI);
            // Add workflow step
            addUpdateConsistencyGroupPolicyStep(workflow, protectionSystem, consistencyGroup, newVirtualPool.getRpCopyMode());
        }
        if (!workflow.getAllStepStatus().isEmpty()) {
            _log.info("The updateAutoTieringPolicy workflow has {} step(s). Starting the workflow.", workflow.getAllStepStatus().size());
            workflow.executePlan(taskCompleter, "Updated the consistency group policy successfully.");
        } else {
            taskCompleter.ready(_dbClient);
        }
    } catch (Exception ex) {
        _log.error("Unexpected exception: ", ex);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
        taskCompleter.error(_dbClient, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) HashMap(java.util.HashMap) VolumeWorkflowCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeWorkflowCompleter) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) LockRetryException(com.emc.storageos.locking.LockRetryException) FunctionalAPIActionFailedException_Exception(com.emc.fapiclient.ws.FunctionalAPIActionFailedException_Exception) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) FunctionalAPIInternalError_Exception(com.emc.fapiclient.ws.FunctionalAPIInternalError_Exception) CoordinatorException(com.emc.storageos.coordinator.exceptions.CoordinatorException) RecoverPointException(com.emc.storageos.recoverpoint.exceptions.RecoverPointException) VolumeVpoolChangeTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter) Volume(com.emc.storageos.db.client.model.Volume) StringSet(com.emc.storageos.db.client.model.StringSet)

Example 2 with VolumeVpoolChangeTaskCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter in project coprhd-controller by CoprHD.

the class BlockDeviceExportController method updateVolumePathParams.

@Override
public void updateVolumePathParams(URI volumeURI, URI newVpoolURI, String opId) throws ControllerException {
    _log.info("Received request to update Volume path parameters. Creating master workflow.");
    VolumeVpoolChangeTaskCompleter taskCompleter = null;
    Volume volume = null;
    try {
        // Read volume from database, update the Vpool to the new completer, and create task completer.
        volume = _dbClient.queryObject(Volume.class, volumeURI);
        URI oldVpoolURI = volume.getVirtualPool();
        List<URI> rollbackList = new ArrayList<URI>();
        List<Volume> updatedVolumes = new ArrayList<Volume>();
        rollbackList.add(volumeURI);
        // Check if it is a VPlex volume, and get backend volumes
        Volume backendSrc = VPlexUtil.getVPLEXBackendVolume(volume, true, _dbClient, false);
        if (backendSrc != null) {
            // Change the back end volume's vpool too
            backendSrc.setVirtualPool(newVpoolURI);
            rollbackList.add(backendSrc.getId());
            updatedVolumes.add(backendSrc);
            // VPlex volume, check if it is distributed
            Volume backendHa = VPlexUtil.getVPLEXBackendVolume(volume, false, _dbClient, false);
            if (backendHa != null && backendHa.getVirtualPool() != null && backendHa.getVirtualPool().toString().equals(oldVpoolURI.toString())) {
                backendHa.setVirtualPool(newVpoolURI);
                rollbackList.add(backendHa.getId());
                updatedVolumes.add(backendHa);
            }
        }
        // The VolumeVpoolChangeTaskCompleter will restore the old Virtual Pool in event of error.
        taskCompleter = new VolumeVpoolChangeTaskCompleter(rollbackList, oldVpoolURI, opId);
        volume.setVirtualPool(newVpoolURI);
        updatedVolumes.add(volume);
        _log.info(String.format("Changing VirtualPool PathParams for volume %s (%s) from %s to %s", volume.getLabel(), volume.getId(), oldVpoolURI, newVpoolURI));
        _dbClient.updateObject(updatedVolumes);
    } catch (Exception ex) {
        _log.error("Unexpected exception reading volume or generating taskCompleter: ", ex);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
        VolumeWorkflowCompleter completer = new VolumeWorkflowCompleter(volumeURI, opId);
        completer.error(_dbClient, serviceError);
    }
    try {
        Workflow workflow = _wfUtils.newWorkflow("updateVolumePathParams", false, opId);
        // Locate all the ExportMasks containing the given volume, and their Export Group.
        Map<ExportMask, ExportGroup> maskToGroupMap = ExportUtils.getExportMasks(volume, _dbClient);
        Map<URI, StringSetMap> maskToZoningMap = new HashMap<URI, StringSetMap>();
        // Store the original zoning maps of the export masks to be used to restore in case of a failure
        for (ExportMask mask : maskToGroupMap.keySet()) {
            maskToZoningMap.put(mask.getId(), mask.getZoningMap());
        }
        taskCompleter.setMaskToZoningMap(maskToZoningMap);
        // Acquire all necessary locks for the workflow:
        // For each export group lock initiator's hosts and storage array keys.
        List<URI> initiatorURIs = new ArrayList<URI>();
        for (ExportGroup exportGroup : maskToGroupMap.values()) {
            initiatorURIs.addAll(StringSetUtil.stringSetToUriList(exportGroup.getInitiators()));
            List<String> lockKeys = ControllerLockingUtil.getHostStorageLockKeys(_dbClient, ExportGroup.ExportGroupType.valueOf(exportGroup.getType()), initiatorURIs, volume.getStorageController());
            initiatorURIs.clear();
            boolean acquiredLocks = _wfUtils.getWorkflowService().acquireWorkflowLocks(workflow, lockKeys, LockTimeoutValue.get(LockType.EXPORT_GROUP_OPS));
            if (!acquiredLocks) {
                throw DeviceControllerException.exceptions.failedToAcquireLock(lockKeys.toString(), "UpdateVolumePathParams: " + volume.getLabel());
            }
        }
        // These steps are serialized, which is required in case an ExportMask appears
        // in multiple Export Groups.
        String stepId = null;
        for (ExportGroup exportGroup : maskToGroupMap.values()) {
            stepId = _wfUtils.generateExportChangePathParams(workflow, "changePathParams", stepId, volume.getStorageController(), exportGroup.getId(), volumeURI);
        }
        if (!workflow.getAllStepStatus().isEmpty()) {
            _log.info("The updateVolumePathParams workflow has {} steps. Starting the workflow.", workflow.getAllStepStatus().size());
            workflow.executePlan(taskCompleter, "Update the export group on all storage systems successfully.");
        } else {
            taskCompleter.ready(_dbClient);
        }
    } catch (Exception ex) {
        _log.error("Unexpected exception: ", ex);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
        taskCompleter.error(_dbClient, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) HashMap(java.util.HashMap) VolumeWorkflowCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeWorkflowCompleter) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) URI(java.net.URI) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) LockRetryException(com.emc.storageos.locking.LockRetryException) VolumeVpoolChangeTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) Volume(com.emc.storageos.db.client.model.Volume)

Example 3 with VolumeVpoolChangeTaskCompleter

use of com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter in project coprhd-controller by CoprHD.

the class BlockOrchestrationDeviceController method changeVirtualPool.

/*
     * (non-Javadoc)
     * 
     * @see
     * com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController#changeVirtualPool(java.util.List,
     * java.lang.String)
     */
@Override
public void changeVirtualPool(List<VolumeDescriptor> volumes, String taskId) throws ControllerException {
    Map<URI, URI> volumeToOldVpoolsMap = VolumeDescriptor.createVolumeToOldVpoolMap(volumes);
    Map<URI, URI> volumeToNewVpoolsMap = VolumeDescriptor.createVolumeToNewVpoolMap(volumes);
    List<URI> volURIs = VolumeDescriptor.getVolumeURIs(volumes);
    List<URI> cgIds = null;
    List<URI> migrationURIs = new ArrayList<URI>();
    for (VolumeDescriptor desc : volumes) {
        URI migrationURI = desc.getMigrationId();
        if (!NullColumnValueGetter.isNullURI(migrationURI)) {
            migrationURIs.add(migrationURI);
        }
        cgIds = Volume.fetchCgIds(s_dbClient, volURIs);
    }
    VolumeVpoolChangeTaskCompleter completer = new VolumeVpoolChangeTaskCompleter(volURIs, migrationURIs, volumeToOldVpoolsMap, volumeToNewVpoolsMap, taskId);
    try {
        // Validate the volume identities before proceeding
        validator.volumeURIs(volURIs, true, true, ValCk.ID, ValCk.VPLEX);
        // Generate the Workflow.
        Workflow workflow = _workflowService.getNewWorkflow(this, CHANGE_VPOOL_WF_NAME, true, taskId, completer);
        // the wait for key returned by previous call
        String waitFor = null;
        // Mainly for RP+VPLEX as a change vpool would require new volumes (source-journal, target(s),
        // target-journal) to be created.
        waitFor = _blockDeviceController.addStepsForCreateVolumes(workflow, waitFor, volumes, taskId);
        // Call the VPlexDeviceController to add change virtual pool steps.
        waitFor = _vplexDeviceController.addStepsForChangeVirtualPool(workflow, waitFor, volumes, taskId);
        // Last, call the RPDeviceController to add change virtual pool steps.
        waitFor = _rpDeviceController.addStepsForChangeVirtualPool(workflow, waitFor, volumes, taskId);
        // This step is currently used to ensure that any existing resources get added to native
        // CGs. Mainly used for VPLEX->RP+VPLEX change vpool. The existing VPLEX volume would not be
        // in any CG and we now need its backing volume(s) to be added to their local array CG.
        waitFor = postRPChangeVpoolSteps(workflow, waitFor, volumes, taskId);
        // Finish up and execute the plan.
        // The Workflow will handle the TaskCompleter
        String successMessage = "Change Virtual Pool suceeded for volumes: " + volURIs.toString();
        Object[] callbackArgs = new Object[] { volURIs };
        workflow.executePlan(completer, successMessage, new WorkflowCallback(), callbackArgs, null, null);
    } catch (Exception ex) {
        s_logger.error("Could not change Virtual Pool for volumes: " + volURIs, ex);
        String opName = ResourceOperationTypeEnum.CHANGE_BLOCK_VOLUME_VPOOL.getName();
        ServiceError serviceError = DeviceControllerException.errors.changeVirtualPoolFailed(volURIs.toString(), opName, ex);
        completer.error(s_dbClient, _locker, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) URI(java.net.URI) WorkflowException(com.emc.storageos.workflow.WorkflowException) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) LockRetryException(com.emc.storageos.locking.LockRetryException) VolumeVpoolChangeTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter) BlockObject(com.emc.storageos.db.client.model.BlockObject)

Aggregations

DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)3 LockRetryException (com.emc.storageos.locking.LockRetryException)3 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)3 ControllerException (com.emc.storageos.volumecontroller.ControllerException)3 VolumeVpoolChangeTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter)3 Workflow (com.emc.storageos.workflow.Workflow)3 URI (java.net.URI)3 ArrayList (java.util.ArrayList)3 Volume (com.emc.storageos.db.client.model.Volume)2 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)2 VolumeWorkflowCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeWorkflowCompleter)2 WorkflowException (com.emc.storageos.workflow.WorkflowException)2 HashMap (java.util.HashMap)2 FunctionalAPIActionFailedException_Exception (com.emc.fapiclient.ws.FunctionalAPIActionFailedException_Exception)1 FunctionalAPIInternalError_Exception (com.emc.fapiclient.ws.FunctionalAPIInternalError_Exception)1 CoordinatorException (com.emc.storageos.coordinator.exceptions.CoordinatorException)1 BlockObject (com.emc.storageos.db.client.model.BlockObject)1 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)1 ExportMask (com.emc.storageos.db.client.model.ExportMask)1 NamedURI (com.emc.storageos.db.client.model.NamedURI)1