Search in sources :

Example 11 with Migration

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

the class VPlexDeviceController method pauseMigrationStep.

public void pauseMigrationStep(URI vplexURI, URI migrationURI, String stepId) {
    WorkflowStepCompleter.stepExecuting(stepId);
    try {
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
        Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
        client.pauseMigrations(Arrays.asList(migration.getLabel()));
        migration.setMigrationStatus(VPlexMigrationInfo.MigrationStatus.PAUSED.getStatusValue());
        _dbClient.updateObject(migration);
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (Exception ex) {
        _log.error("Exception pausing migration: ", ex);
        String opName = ResourceOperationTypeEnum.PAUSE_MIGRATION.getName();
        ServiceError serviceError = VPlexApiException.errors.operateMigrationFailed(opName, ex);
        WorkflowStepCompleter.stepFailed(stepId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) Migration(com.emc.storageos.db.client.model.Migration) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 12 with Migration

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

the class VPlexDeviceController method addStepsForChangeVirtualArray.

@Override
public String addStepsForChangeVirtualArray(Workflow workflow, String waitFor, List<VolumeDescriptor> volumes, String taskId) throws InternalException {
    try {
        URI cgURI = null;
        URI currentVarrayURI = null;
        URI tgtVarrayURI = null;
        URI vplexURI = null;
        StorageSystem vplexSystem = null;
        List<URI> vplexVolumeURIs = new ArrayList<URI>();
        VPlexConsistencyGroupManager cgMgr = null;
        // Get all the Virtual Volumes and the new varray URI.
        List<VolumeDescriptor> vplexVolumeDescriptors = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
        for (VolumeDescriptor vplexVolumeDescriptor : vplexVolumeDescriptors) {
            // Add the URI for the VPLEX volume.
            URI vplexVolumeURI = vplexVolumeDescriptor.getVolumeURI();
            _log.info("Add steps to change virtual array for volume {}", vplexVolumeURI);
            vplexVolumeURIs.add(vplexVolumeURI);
            // Set the target virtual array if not already set.
            if (tgtVarrayURI == null) {
                if ((vplexVolumeDescriptor.getParameters() != null) && (!vplexVolumeDescriptor.getParameters().isEmpty())) {
                    tgtVarrayURI = (URI) vplexVolumeDescriptor.getParameters().get(VolumeDescriptor.PARAM_VARRAY_CHANGE_NEW_VAARAY_ID);
                    _log.info("Target virtual array for varray change is {}", tgtVarrayURI);
                }
            }
            // migrated when multiple volumes are passed.
            if (vplexURI == null) {
                Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
                vplexURI = vplexVolume.getStorageController();
                vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
                currentVarrayURI = vplexVolume.getVirtualArray();
                cgURI = vplexVolume.getConsistencyGroup();
                cgMgr = (VPlexConsistencyGroupManager) getConsistencyGroupManager(vplexVolume);
            }
        }
        // We need to determine if the varray change will migrate the
        // volumes to the other cluster of the VPLEX. If so and the
        // volumes are in a consistency group, then the volumes must
        // first be removed from the consistency group.
        String lastStep = waitFor;
        boolean volumesRemovedFromCG = false;
        if (!NullColumnValueGetter.isNullURI(cgURI)) {
            _log.info("Varray change volumes are in CG {}", cgURI);
            String currentClusterId = ConnectivityUtil.getVplexClusterForVarray(currentVarrayURI, vplexURI, _dbClient);
            String newClusterId = ConnectivityUtil.getVplexClusterForVarray(tgtVarrayURI, vplexURI, _dbClient);
            if (!newClusterId.equals(currentClusterId)) {
                _log.info("Varray change migrates volumes to cluster {}", newClusterId);
                // The volumes are in a consistency group and the
                // volumes will change cluster, so the volumes
                // must be removed from the CG first.
                lastStep = cgMgr.addStepForRemoveVolumesFromCG(workflow, waitFor, vplexSystem, vplexVolumeURIs, cgURI);
                volumesRemovedFromCG = true;
            }
        }
        // Create steps to migrate the backend volumes.
        String migrateStep = null;
        List<URI> localSystemsToRemoveCG = new ArrayList<URI>();
        List<VolumeDescriptor> vplexMigrateVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_MIGRATE_VOLUME }, new VolumeDescriptor.Type[] {});
        for (URI vplexVolumeURI : vplexVolumeURIs) {
            _log.info("Adding migration steps for vplex volume {}", vplexVolumeURI);
            // A list of the volumes to which the data on the current
            // backend volumes will be migrated.
            List<URI> newVolumes = new ArrayList<URI>();
            // A Map containing a migration for each new backend
            // volume
            Map<URI, URI> migrationMap = new HashMap<URI, URI>();
            // A map that specifies the storage pool in which
            // each new volume should be created.
            Map<URI, URI> poolVolumeMap = new HashMap<URI, URI>();
            for (VolumeDescriptor desc : vplexMigrateVolumes) {
                // Skip migration targets that are not for the VPLEX
                // volume being processed.
                Migration migration = getDataObject(Migration.class, desc.getMigrationId(), _dbClient);
                if (!migration.getVolume().equals(vplexVolumeURI)) {
                    continue;
                }
                _log.info("Found migration {} for VPLEX volume", migration.getId());
                // Set data required to add the migration steps.
                newVolumes.add(desc.getVolumeURI());
                migrationMap.put(desc.getVolumeURI(), desc.getMigrationId());
                poolVolumeMap.put(desc.getVolumeURI(), desc.getPoolURI());
                // If the migration is to a different storage system
                // we may need to remove the backend CG on the source
                // system after the migration completes.
                URI migSrcURI = migration.getSource();
                Volume migSrc = getDataObject(Volume.class, migSrcURI, _dbClient);
                URI migTgtURI = migration.getTarget();
                Volume migTgt = getDataObject(Volume.class, migTgtURI, _dbClient);
                if ((!migTgt.getStorageController().equals(migSrc.getStorageController())) && (!localSystemsToRemoveCG.contains(migSrc.getStorageController()))) {
                    _log.info("Will remove CG on local system {} if volume is in a CG.", migSrc.getStorageController());
                    localSystemsToRemoveCG.add(migSrc.getStorageController());
                }
            }
            // Note that the migrate step here is a step group associated
            // with deleting the migration sources after the migrations
            // have completed and committed. This means that anything
            // that waits on this, will occur after the migrations have
            // completed, been committed, and the migration sources deleted.
            migrateStep = addStepsForMigrateVolumes(workflow, vplexURI, vplexVolumeURI, newVolumes, migrationMap, poolVolumeMap, null, tgtVarrayURI, false, false, taskId, lastStep);
            _log.info("Added migration steps for vplex volume {}", vplexVolumeURI);
        }
        // Update last step
        if (migrateStep != null) {
            lastStep = migrateStep;
        }
        // If the volumes are in a CG, we add the final CG steps.
        if (!NullColumnValueGetter.isNullURI(cgURI)) {
            BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, _dbClient);
            if (volumesRemovedFromCG) {
                // If the volumes were removed from the consistency group, the
                // varray change was across clusters. First add a step to delete
                // the CG on the old cluster and then add steps to create the
                // CG on the other cluster and add the volumes. The remove step
                // must be executed first otherwise, when we go to create the CG
                // on the other cluster, the create CG code will see that the CG
                // already exists on the VPLEX system and it will not create it.
                String removeStepId = workflow.createStepId();
                StringSet systemCGs = cg.getSystemConsistencyGroups().get(vplexURI.toString());
                String clusterCGName = systemCGs.iterator().next();
                String clusterName = BlockConsistencyGroupUtils.fetchClusterName(clusterCGName);
                String cgName = BlockConsistencyGroupUtils.fetchCgName(clusterCGName);
                cgMgr.addStepForRemoveVPlexCG(workflow, removeStepId, lastStep, vplexSystem, cgURI, cgName, clusterName, Boolean.FALSE, null);
                lastStep = cgMgr.addStepsForCreateConsistencyGroup(workflow, removeStepId, vplexSystem, vplexVolumeURIs, true);
                _log.info("Added steps to remove the CG from the source cluster and add to target cluster.");
            }
            if (cg.checkForType(Types.LOCAL)) {
                _log.info("CG {} has local type", cgURI);
                // If the backend volumes are being migrated to a new storage system,
                // then we need to add a step to delete the local CG.
                boolean localCGDeleted = false;
                List<URI> localSystemURIs = BlockConsistencyGroupUtils.getLocalSystems(cg, _dbClient);
                for (URI localSystemURI : localSystemURIs) {
                    _log.info("CG exists on local system {}", localSystemURI);
                    if (localSystemsToRemoveCG.contains(localSystemURI)) {
                        localCGDeleted = true;
                        _log.info("Adding step to remove CG on local system{}", localSystemURI);
                        StorageSystem localSystem = getDataObject(StorageSystem.class, localSystemURI, _dbClient);
                        Workflow.Method deleteCGMethod = new Workflow.Method("deleteConsistencyGroup", localSystemURI, cgURI, Boolean.FALSE);
                        workflow.createStep("deleteLocalCG", String.format("Delete consistency group from storage system: %s", localSystemURI), lastStep, localSystemURI, localSystem.getSystemType(), BlockDeviceController.class, deleteCGMethod, null, null);
                    }
                }
                if (localCGDeleted) {
                    lastStep = "deleteLocalCG";
                }
            }
        }
        // Return the last step
        return lastStep;
    } catch (Exception ex) {
        throw VPlexApiException.exceptions.addStepsForChangeVirtualPoolFailed(ex);
    }
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) HashMap(java.util.HashMap) Migration(com.emc.storageos.db.client.model.Migration) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup) Volume(com.emc.storageos.db.client.model.Volume) StringSet(com.emc.storageos.db.client.model.StringSet) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 13 with Migration

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

the class VPlexDeviceController method pauseMigration.

@Override
public void pauseMigration(URI vplexURI, URI migrationURI, String opId) {
    MigrationOperationTaskCompleter completer = null;
    try {
        // Generate the Workflow.
        Workflow workflow = _workflowService.getNewWorkflow(this, PAUSE_MIGRATION_WF_NAME, false, opId);
        _log.info("Created pause migration workflow with operation id {}", opId);
        StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
        Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
        URI volId = migration.getVolume();
        completer = new MigrationOperationTaskCompleter(volId, opId);
        Workflow.Method pauseMigrationMethod = new Workflow.Method(PAUSE_MIGRATION_METHOD_NAME, vplexURI, migrationURI);
        workflow.createStep(PAUSE_MIGRATION_STEP, "Pause migration", null, vplexURI, vplex.getSystemType(), getClass(), pauseMigrationMethod, rollbackMethodNullMethod(), null);
        String successMsg = String.format("Migration %s paused successfully", migrationURI);
        workflow.executePlan(completer, successMsg);
        _log.info("Workflow plan executing");
    } catch (Exception e) {
        String failMsg = String.format("Pause the migration %s failed", migrationURI);
        _log.error(failMsg, e);
        String opName = ResourceOperationTypeEnum.PAUSE_MIGRATION.getName();
        ServiceError serviceError = VPlexApiException.errors.operateMigrationFailed(opName, e);
        failStep(completer, opId, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) MigrationOperationTaskCompleter(com.emc.storageos.vplexcontroller.completers.MigrationOperationTaskCompleter) Migration(com.emc.storageos.db.client.model.Migration) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 14 with Migration

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

the class VPlexDeviceController method addStepsForChangeVirtualPool.

@Override
public String addStepsForChangeVirtualPool(Workflow workflow, String waitFor, List<VolumeDescriptor> volumes, String taskId) throws InternalException {
    try {
        // Get all the Virtual Volumes.
        List<VolumeDescriptor> vplexVirtualVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
        if (vplexVirtualVolumes == null || vplexVirtualVolumes.isEmpty()) {
            return waitFor;
        }
        // Find the original change vpool virtual volumes from the descriptors.
        URI newVpoolURI = null;
        List<URI> changeVpoolVirtualVolumeURIs = new ArrayList<URI>();
        for (VolumeDescriptor vplexVirtualVolume : vplexVirtualVolumes) {
            if (vplexVirtualVolume.getParameters() != null && !vplexVirtualVolume.getParameters().isEmpty()) {
                // Let's check to see if the PARAM_VPOOL_CHANGE_EXISTING_VOLUME_ID was populated
                // in the descriptor params map. This would indicate that the descriptor
                // has information about the existing volume for the change vpool operation.
                Object existingVolumeId = vplexVirtualVolume.getParameters().get(VolumeDescriptor.PARAM_VPOOL_CHANGE_EXISTING_VOLUME_ID);
                if (existingVolumeId != null) {
                    URI virtualVolumeURI = (URI) existingVolumeId;
                    _log.info(String.format("Adding steps for change vpool for vplex volume %s", virtualVolumeURI.toString()));
                    if (newVpoolURI == null) {
                        newVpoolURI = (URI) vplexVirtualVolume.getParameters().get(VolumeDescriptor.PARAM_VPOOL_CHANGE_NEW_VPOOL_ID);
                    }
                    changeVpoolVirtualVolumeURIs.add(virtualVolumeURI);
                }
            }
        }
        // Check to see if this is an RP+VPLEX change vpool request
        List<VolumeDescriptor> rpExistingSourceVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_EXISTING_SOURCE }, new VolumeDescriptor.Type[] {});
        // Check to see if this is an RP+VPLEX change vpool request
        List<VolumeDescriptor> rpExistingProtectedSourceVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_EXISTING_PROTECTED_SOURCE }, new VolumeDescriptor.Type[] {});
        boolean rpAddProtectionVPoolChange = (rpExistingSourceVolumes != null && !rpExistingSourceVolumes.isEmpty());
        boolean rpUpgradeProtectionVPoolChange = (rpExistingProtectedSourceVolumes != null && !rpExistingProtectedSourceVolumes.isEmpty());
        // RP+VPLEX change vpool request
        if (rpAddProtectionVPoolChange || rpUpgradeProtectionVPoolChange) {
            // First let's make a copy of the all the volume descriptors passed in
            List<VolumeDescriptor> copyOfVolumeDescriptors = new ArrayList<VolumeDescriptor>();
            copyOfVolumeDescriptors.addAll(volumes);
            if (rpAddProtectionVPoolChange) {
                _log.info("Adding VPLEX steps for RP+VPLEX/MetroPoint add protection vpool change...");
                Iterator<VolumeDescriptor> it = copyOfVolumeDescriptors.iterator();
                while (it.hasNext()) {
                    VolumeDescriptor currentVolumeDesc = it.next();
                    if (changeVpoolVirtualVolumeURIs.contains(currentVolumeDesc.getVolumeURI())) {
                        // Remove the RP+VPLEX Source Change Vpool Virtual Volume(s) from the copy of the
                        // descriptors as they do not need to be created (because they already exist!)
                        it.remove();
                        break;
                    }
                }
                // already)
                for (URI virtualVolumeURI : changeVpoolVirtualVolumeURIs) {
                    Volume changeVpoolVolume = getDataObject(Volume.class, virtualVolumeURI, _dbClient);
                    changeVpoolVolume.getConsistencyGroup();
                    // This is a good time to update the vpool on the existing Virtual Volume to the new vpool
                    changeVpoolVolume.setVirtualPool(newVpoolURI);
                    _dbClient.updateObject(changeVpoolVolume);
                    StorageSystem vplex = getDataObject(StorageSystem.class, changeVpoolVolume.getStorageController(), _dbClient);
                    // Get a handle on the RP consistency group manager
                    ConsistencyGroupManager consistencyGroupManager = getConsistencyGroupManager(DiscoveredDataObject.Type.rp.name());
                    // Add step for create CG
                    waitFor = consistencyGroupManager.addStepsForCreateConsistencyGroup(workflow, waitFor, vplex, Arrays.asList(virtualVolumeURI), false);
                    _log.info("Added steps for CG creation for vplex volume {}", virtualVolumeURI);
                }
            } else {
                _log.info("Adding VPLEX steps for RP+VPLEX/MetroPoint upgrade protection vpool change...");
            }
            // Let's now create the virtual volumes for the RP+VPLEX:
            // Source Journal, Target(s), and Target Journal.
            waitFor = addStepsForCreateVolumes(workflow, waitFor, copyOfVolumeDescriptors, taskId);
        }
        // Create steps to migrate the backend volumes.
        String lastStep = waitFor;
        URI cgURI = null;
        // With application support, one VPLEX CG could have multiple replication groups from the same local system.
        // The localSystemToRemoveCG map key is storagesystemUri, value is the list of replication group names to be removed.
        Map<URI, Set<String>> localSystemsToRemoveCG = new HashMap<URI, Set<String>>();
        List<VolumeDescriptor> vplexMigrateVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_MIGRATE_VOLUME }, new VolumeDescriptor.Type[] {});
        if (vplexMigrateVolumes != null && !vplexMigrateVolumes.isEmpty()) {
            for (URI virtualVolumeURI : changeVpoolVirtualVolumeURIs) {
                _log.info("Adding migration steps for vplex volume {}", virtualVolumeURI);
                // A list of the volumes satisfying the new VirtualPool to
                // which the data on the current backend volumes
                // will be migrated.
                List<URI> newVolumes = new ArrayList<URI>();
                // A Map containing a migration for each new backend
                // volume
                Map<URI, URI> migrationMap = new HashMap<URI, URI>();
                // A map that specifies the storage pool in which
                // each new volume should be created.
                Map<URI, URI> poolVolumeMap = new HashMap<URI, URI>();
                // The URI of the vplex system
                URI vplexURI = null;
                for (VolumeDescriptor desc : vplexMigrateVolumes) {
                    // Skip migration targets that are not for the VPLEX
                    // volume being processed.
                    Migration migration = getDataObject(Migration.class, desc.getMigrationId(), _dbClient);
                    if (!migration.getVolume().equals(virtualVolumeURI)) {
                        continue;
                    }
                    // migrated when multiple volumes are passed.
                    if (vplexURI == null) {
                        Volume virtualVolume = getDataObject(Volume.class, virtualVolumeURI, _dbClient);
                        vplexURI = virtualVolume.getStorageController();
                        cgURI = virtualVolume.getConsistencyGroup();
                    }
                    // Set data required to add the migration steps.
                    newVolumes.add(desc.getVolumeURI());
                    migrationMap.put(desc.getVolumeURI(), desc.getMigrationId());
                    poolVolumeMap.put(desc.getVolumeURI(), desc.getPoolURI());
                    // If the migration is to a different storage system
                    // we may need to remove the backend CG on the source
                    // system after the migration completes. Note that the
                    // migration source is null for an ingested volume
                    // being migrated to known storage.
                    Volume migSrc = null;
                    URI migSrcURI = migration.getSource();
                    if (!NullColumnValueGetter.isNullURI(migSrcURI)) {
                        migSrc = getDataObject(Volume.class, migSrcURI, _dbClient);
                    }
                    URI migTgtURI = migration.getTarget();
                    Volume migTgt = getDataObject(Volume.class, migTgtURI, _dbClient);
                    if ((migSrc != null) && (!migTgt.getStorageController().equals(migSrc.getStorageController()))) {
                        // If we have a volume to migrate and the RG field is NOT set on the volume,
                        // do not remove the RG on the local system.
                        // 
                        // Volumes that are in RGs that are being migrated are grouped together so otherwise
                        // we're good as the replication instance will be set on those volumes.
                        String rgName = migSrc.getReplicationGroupInstance();
                        if (NullColumnValueGetter.isNotNullValue(rgName)) {
                            URI storageUri = migSrc.getStorageController();
                            Set<String> rgNames = localSystemsToRemoveCG.get(storageUri);
                            if (rgNames == null) {
                                rgNames = new HashSet<String>();
                                localSystemsToRemoveCG.put(storageUri, rgNames);
                            }
                            rgNames.add(rgName);
                            _log.info("Will remove CG {} on local system {}", rgName, storageUri);
                        } else {
                            _log.info("Will not remove CG on local system {}", migSrc.getStorageController());
                        }
                    }
                }
                // Note that the last step here is a step group associated
                // with deleting the migration sources after the migrations
                // have completed and committed. This means that anything
                // that waits on this, will occur after the migrations have
                // completed, been committed, and the migration sources deleted.
                lastStep = addStepsForMigrateVolumes(workflow, vplexURI, virtualVolumeURI, newVolumes, migrationMap, poolVolumeMap, newVpoolURI, null, VolumeDescriptor.getMigrationSuspendBeforeCommit(volumes), VolumeDescriptor.getMigrationSuspendBeforeDeleteSource(volumes), taskId, waitFor);
                _log.info("Add migration steps for vplex volume {}", virtualVolumeURI);
            }
            // systemConsistencyGroup specified for the group.
            if (!NullColumnValueGetter.isNullURI(cgURI)) {
                _log.info("Vpool change volumes are in CG {}", cgURI);
                BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, _dbClient);
                if (cg.checkForType(Types.LOCAL)) {
                    _log.info("CG {} has local type", cgURI);
                    // If any of the VPLEX volumes involved in the vpool change
                    // is in a VPLEX CG with corresponding local CGs for the backend
                    // volumes, then it is required that all VPLEX volumes in the
                    // CG are part of the vpool change. If the backend volumes are being
                    // migrated to a new storage system, then we need to add a step
                    // to delete the local CG.
                    boolean localCGDeleted = false;
                    for (Map.Entry<URI, Set<String>> entry : localSystemsToRemoveCG.entrySet()) {
                        localCGDeleted = true;
                        URI localSystemURI = entry.getKey();
                        StorageSystem localSystem = getDataObject(StorageSystem.class, localSystemURI, _dbClient);
                        Set<String> rgNames = entry.getValue();
                        for (String rgName : rgNames) {
                            _log.info("Adding step to remove CG {} on local system {}", rgName, localSystemURI);
                            Workflow.Method deleteCGMethod = new Workflow.Method("deleteReplicationGroupInConsistencyGroup", localSystemURI, cgURI, rgName, false, false, true);
                            workflow.createStep("deleteLocalCG", String.format("Delete consistency group from storage system: %s", localSystemURI), lastStep, localSystemURI, localSystem.getSystemType(), BlockDeviceController.class, deleteCGMethod, null, null);
                        }
                    }
                    if (localCGDeleted) {
                        lastStep = "deleteLocalCG";
                    }
                }
            }
        }
        // Return the last step
        return lastStep;
    } catch (Exception ex) {
        throw VPlexApiException.exceptions.addStepsForChangeVirtualPoolFailed(ex);
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) StringSet(com.emc.storageos.db.client.model.StringSet) HashMap(java.util.HashMap) Migration(com.emc.storageos.db.client.model.Migration) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Workflow(com.emc.storageos.workflow.Workflow) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) BlockConsistencyGroup(com.emc.storageos.db.client.model.BlockConsistencyGroup) Volume(com.emc.storageos.db.client.model.Volume) BlockObject(com.emc.storageos.db.client.model.BlockObject) DiscoveredDataObject(com.emc.storageos.db.client.model.DiscoveredDataObject) DataObject(com.emc.storageos.db.client.model.DataObject) VPlexControllerUtils.getDataObject(com.emc.storageos.vplexcontroller.VPlexControllerUtils.getDataObject) Map(java.util.Map) OpStatusMap(com.emc.storageos.db.client.model.OpStatusMap) HashMap(java.util.HashMap) StringMap(com.emc.storageos.db.client.model.StringMap)

Example 15 with Migration

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

the class VPlexDeviceController method rollbackMigrateVirtualVolume.

/**
 * Called when a migration cannot be created and started or the data
 * migration is terminated prior to completing successfully. The function
 * tries to cancel the migration and cleanup the remnants of the migration
 * on the VPLEX.
 *
 * @param vplexURI
 *            The URI of the VPLex storage system.
 * @param migrationURI
 *            The URI of the migration.
 * @param migrateStepId
 *            The migration step id.
 * @param stepId
 *            The rollback step id.
 * @throws WorkflowException
 */
public void rollbackMigrateVirtualVolume(URI vplexURI, URI migrationURI, String migrateStepId, String stepId) throws WorkflowException {
    Migration migration = null;
    String migrationVolumeLabel = null;
    try {
        // Update step state to executing.
        WorkflowStepCompleter.stepExecuting(stepId);
        // Was the migration created and started? If so, then
        // we'll try and cancel the migration and clean up.
        // Otherwise, there is nothing to do.
        Boolean migrationStarted = (Boolean) _workflowService.loadStepData(migrateStepId);
        if (!migrationStarted.booleanValue()) {
            // The migration was not successfully started.
            WorkflowStepCompleter.stepSucceded(stepId);
            return;
        }
        // Get the migration.
        migration = _dbClient.queryObject(Migration.class, migrationURI);
        // Get the VPLEX volume for the migration.
        Volume migrationVolume = _dbClient.queryObject(Volume.class, migration.getVolume());
        if (migrationVolume != null) {
            migrationVolumeLabel = migrationVolume.getLabel();
        }
        // cancel it now.
        if (!VPlexMigrationInfo.MigrationStatus.CANCELLED.getStatusValue().equals(migration.getMigrationStatus())) {
            _log.info("Cancel migration {}", migrationURI);
            // Get the VPlex API client.
            StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
            VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
            _log.info("Got VPlex API client for VPlex {}", vplexURI);
            // Try to cancel the migration and cleanup and remove any
            // remnants of the migration.
            client.cancelMigrations(Arrays.asList(migration.getLabel()), true, true);
            _log.info("Migration cancelled");
        }
        WorkflowStepCompleter.stepSucceded(stepId);
    } catch (VPlexApiException vae) {
        // Do not allow rollback to go any further COP-21257
        _workflowService.setWorkflowRollbackContOnError(stepId, false);
        _log.error("Error during rollback of start migration: {}", vae.getMessage(), vae);
        if (migration != null) {
            setOrClearVolumeInternalFlag(migration.getVolume(), true);
            vae = VPlexApiException.exceptions.migrationRollbackFailureContactEMC(migration.getVolume().toString(), migrationVolumeLabel, migration.getLabel());
        }
        WorkflowStepCompleter.stepFailed(stepId, vae);
    } catch (Exception e) {
        _log.error("Error during rollback of start migration: {}", e.getMessage());
        // Do not allow rollback to go any further COP-21257
        _workflowService.setWorkflowRollbackContOnError(stepId, false);
        if (migration != null) {
            setOrClearVolumeInternalFlag(migration.getVolume(), true);
            e = VPlexApiException.exceptions.migrationRollbackFailureContactEMC(migration.getVolume().toString(), migrationVolumeLabel, migration.getLabel());
        }
        WorkflowStepCompleter.stepFailed(stepId, VPlexApiException.exceptions.rollbackMigrateVolume(migrationURI.toString(), e));
    }
}
Also used : Volume(com.emc.storageos.db.client.model.Volume) Migration(com.emc.storageos.db.client.model.Migration) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Aggregations

Migration (com.emc.storageos.db.client.model.Migration)33 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)22 URI (java.net.URI)22 Volume (com.emc.storageos.db.client.model.Volume)20 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)18 URISyntaxException (java.net.URISyntaxException)17 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)16 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)16 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)16 ControllerException (com.emc.storageos.volumecontroller.ControllerException)16 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)16 WorkflowException (com.emc.storageos.workflow.WorkflowException)16 IOException (java.io.IOException)16 NamedURI (com.emc.storageos.db.client.model.NamedURI)14 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)12 ArrayList (java.util.ArrayList)10 VPlexApiClient (com.emc.storageos.vplex.api.VPlexApiClient)9 CheckPermission (com.emc.storageos.security.authorization.CheckPermission)8 HashMap (java.util.HashMap)8 VolumeDescriptor (com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor)7