Search in sources :

Example 46 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VplexDBCkr method checkVolumesOnVplex.

public void checkVolumesOnVplex(URI vplexSystemURI, boolean deleteInvalidVolumes) {
    URIQueryResultList result = new URIQueryResultList();
    List<URI> deletevirtualvolumeURIs = new ArrayList<URI>();
    int nerrors = 0;
    int invalidVolumeCount = 0;
    dbClient.queryByConstraint(ContainmentConstraint.Factory.getStorageDeviceVolumeConstraint(vplexSystemURI), result);
    Iterator<URI> iter = result.iterator();
    VPlexApiClient client = getVPlexApiClient(vplexSystemURI);
    // Get all the virtual volumes. We elect for shallow here as it's quicker-
    // we will spend time below getting details.
    writeLog("Retrieving all virtual volumes... this will take some time...");
    Map<String, VPlexVirtualVolumeInfo> vvInfoMap = client.getVirtualVolumes(true);
    List<VPlexStorageViewInfo> storageViews = client.getStorageViewsLite();
    writeLog("... done");
    try {
        while (iter.hasNext()) {
            Volume volume = dbClient.queryObject(Volume.class, iter.next());
            if (volume == null || volume.getInactive()) {
                continue;
            }
            writeLog(String.format("Checking volume %s (%s)", volume.getLabel(), volume.getDeviceLabel()));
            if (volume.getAssociatedVolumes() == null || volume.getAssociatedVolumes().isEmpty()) {
                writeLog(String.format("Volume %s (%s) has no associated volumes... skipping", volume.getLabel(), volume.getDeviceLabel()));
                continue;
            }
            VPlexVirtualVolumeInfo vvInfo = vvInfoMap.get(volume.getDeviceLabel());
            if (vvInfo == null) {
                writeLog(String.format("ERROR: Volume %s (%s) had no VirtualVolumeInfo in VPlex", volume.getLabel(), volume.getDeviceLabel()));
                deletevirtualvolumeURIs.add(volume.getId());
                nerrors++;
                invalidVolumeCount++;
                continue;
            }
            if ((null != vvInfo.getWwn()) && (null != volume.getWWN())) {
                if (vvInfo.getName().equals(volume.getDeviceLabel())) {
                    if (vvInfo.getWwn().toUpperCase().equals(volume.getWWN().toUpperCase())) {
                        writeLog(String.format("Virtual Volume %s wwn %s matches VPLEX", vvInfo.getName(), vvInfo.getWwn()));
                    } else {
                        writeLog(String.format("ERROR: Virtual Volume %s wwn %s in VPLEX mismatch with viprdb %s", vvInfo.getName(), vvInfo.getWwn(), volume.getWWN()));
                        deletevirtualvolumeURIs.add(volume.getId());
                        invalidVolumeCount++;
                        nerrors++;
                    }
                }
            }
            StringSet wwns = new StringSet();
            for (String cluster : vvInfo.getClusters()) {
                Map<String, VPlexStorageVolumeInfo> svInfoMap = client.getStorageVolumeInfoForDevice(vvInfo.getSupportingDevice(), vvInfo.getLocality(), cluster, false);
                for (String wwn : svInfoMap.keySet()) {
                    // writeLog("adding wwn " + wwn.toUpperCase());
                    wwns.add(wwn.toUpperCase());
                    VPlexStorageVolumeInfo svInfo = svInfoMap.get(wwn);
                    writeLog(String.format("StorageVolume wwn %s name %s cluster %s", wwn, svInfo.getName(), cluster));
                }
            }
            // Now check associated volumes against the wwns.
            for (String associatedVolume : volume.getAssociatedVolumes()) {
                Volume assocVolume = dbClient.queryObject(Volume.class, URI.create(associatedVolume));
                if (assocVolume == null) {
                    writeLog("Associated volunme not found in database... skipping: " + associatedVolume);
                    continue;
                }
                if (wwns.contains(assocVolume.getWWN().toUpperCase())) {
                    writeLog(String.format("Volume %s wwn %s matches VPLEX", assocVolume.getLabel(), assocVolume.getWWN()));
                } else {
                    writeLog(String.format("ERROR: Volume %s wwn %s is not present in VPLEX", assocVolume.getLabel(), assocVolume.getWWN()));
                    nerrors++;
                }
            }
            List<ExportMask> exportMaskListInDB = isVolumeExported(volume.getId());
            if (null != exportMaskListInDB) {
                for (ExportMask exportMaskInDB : exportMaskListInDB) {
                    boolean found = false;
                    boolean storageviewfound = false;
                    for (VPlexStorageViewInfo storageView : storageViews) {
                        if (storageView.getName().equals(exportMaskInDB.getMaskName())) {
                            storageviewfound = true;
                            for (String volumeNameStr : storageView.getVirtualVolumes()) {
                                String[] tokens = volumeNameStr.split(",");
                                String volumeName = tokens[1];
                                if (volumeName.equals(volume.getDeviceLabel())) {
                                    found = true;
                                    break;
                                }
                            }
                            if (!found) {
                                writeLog(String.format("ERROR: volume %s is in exportmask %s in viprdb  but not in vplex storageview %s", volume.getDeviceLabel(), exportMaskInDB.getMaskName(), storageView.getName()));
                                nerrors++;
                            }
                            break;
                        }
                    }
                    if (!storageviewfound) {
                        writeLog(String.format("ERROR: volume %s is in exportmask %s in viprdb  but storageview not found in vplex", volume.getDeviceLabel(), exportMaskInDB.getMaskName()));
                        nerrors++;
                    }
                }
            }
            for (VPlexStorageViewInfo storageView : storageViews) {
                writeLog(String.format("Checking Storageview %s", storageView.getName()));
                for (String volumeNameStr : storageView.getVirtualVolumes()) {
                    String[] tokens = volumeNameStr.split(",");
                    String volumeName = tokens[1];
                    if (volumeName.equals(volume.getDeviceLabel())) {
                        boolean storageviewfound = false;
                        if (null != exportMaskListInDB) {
                            for (ExportMask exportMaskInDB : exportMaskListInDB) {
                                if (storageView.getName().equals(exportMaskInDB.getMaskName())) {
                                    storageviewfound = true;
                                    break;
                                }
                            }
                        }
                        if (!storageviewfound) {
                            writeLog(String.format("ERROR: volume %s is in vplex storageview %s but not in viprdb exportmask", volumeName, storageView.getName()));
                            nerrors++;
                        }
                    }
                }
            }
        }
        if (deleteInvalidVolumes) {
            writeLog("deleting invalid volumes");
            // deleting virtual volumes that no longer exist in vplex
            List<VolumeDescriptor> volumeDescriptors = getDescriptorsForVolumesToBeDeleted(vplexSystemURI, deletevirtualvolumeURIs, VolumeDeleteTypeEnum.VIPR_ONLY.name());
            cleanupForViPROnlyDelete(volumeDescriptors);
            // Mark them inactive. Note that some of the volumes may be mirrors,
            // which have a different database type.
            List<VolumeDescriptor> descriptorsForMirrors = VolumeDescriptor.getDescriptors(volumeDescriptors, VolumeDescriptor.Type.BLOCK_MIRROR);
            dbClient.markForDeletion(dbClient.queryObject(BlockMirror.class, VolumeDescriptor.getVolumeURIs(descriptorsForMirrors)));
            List<VolumeDescriptor> descriptorsForVolumes = VolumeDescriptor.filterByType(volumeDescriptors, null, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.BLOCK_MIRROR });
            dbClient.markForDeletion(dbClient.queryObject(Volume.class, VolumeDescriptor.getVolumeURIs(descriptorsForVolumes)));
            // Update the task status for each volume
            for (URI volumeURI : deletevirtualvolumeURIs) {
                Volume volume = dbClient.queryObject(Volume.class, volumeURI);
                dbClient.updateObject(volume);
            }
        }
    } catch (Exception e) {
        writeLog(String.format("Exception: while verifying virtual volumes", e));
    }
    // List<URI> maskUrislist = new ArrayList<URI>();;
    // maskUrislist.add(URI.create("urn:storageos:ExportMask:3742e612-cc93-422b-a1a5-43490e0fe8ea:vdc1"));
    // for (URI mskUri : maskUrislist) {
    // boolean found = false;
    // ExportMask exportMaskUri = dbClient.queryObject(ExportMask.class, mskUri);
    // if (exportMaskUri == null || exportMaskUri.getInactive()) {
    // continue;
    // }
    // writeLog(String.format("exportMaskUri in ViPR DB is %s", exportMaskUri.getMaskName()));
    // for (VPlexStorageViewInfo storageView : storageViews) {
    // if (storageView.getName().equals(exportMaskUri.getMaskName())) {
    // found = true;
    // }
    // }
    // if(!found) {
    // writeLog(String.format("ERROR: exportMask not found in vplex %s",exportMaskUri.getMaskName()));
    // nerrors++;
    // }
    // }
    writeLog("Total errors for this VPLEX: " + nerrors);
}
Also used : VPlexStorageViewInfo(com.emc.storageos.vplex.api.VPlexStorageViewInfo) VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) BlockMirror(com.emc.storageos.db.client.model.BlockMirror) ExportMask(com.emc.storageos.db.client.model.ExportMask) ArrayList(java.util.ArrayList) URI(java.net.URI) VPlexVirtualVolumeInfo(com.emc.storageos.vplex.api.VPlexVirtualVolumeInfo) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) ContainmentConstraint(com.emc.storageos.db.client.constraint.ContainmentConstraint) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) Volume(com.emc.storageos.db.client.model.Volume) VPlexStorageVolumeInfo(com.emc.storageos.vplex.api.VPlexStorageVolumeInfo) VPlexApiClient(com.emc.storageos.vplex.api.VPlexApiClient) StringSet(com.emc.storageos.db.client.model.StringSet)

Example 47 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VplexDBCkr method getDescriptorsForVolumesToBeDeleted.

public List<VolumeDescriptor> getDescriptorsForVolumesToBeDeleted(URI systemURI, List<URI> volumeURIs, String deletionType) {
    List<VolumeDescriptor> volumeDescriptors = new ArrayList<VolumeDescriptor>();
    for (URI volumeURI : volumeURIs) {
        Volume volume = dbClient.queryObject(Volume.class, volumeURI);
        VolumeDescriptor descriptor = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_VIRT_VOLUME, systemURI, volumeURI, null, null);
        volumeDescriptors.add(descriptor);
        // Add a descriptor for each of the associated volumes.
        if (!volume.isIngestedVolumeWithoutBackend(dbClient) && (null != volume.getAssociatedVolumes())) {
            for (String assocVolId : volume.getAssociatedVolumes()) {
                Volume assocVolume = dbClient.queryObject(Volume.class, URI.create(assocVolId));
                if (null != assocVolume && !assocVolume.getInactive() && assocVolume.getNativeId() != null) {
                    VolumeDescriptor assocDesc = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, assocVolume.getStorageController(), assocVolume.getId(), null, null);
                    volumeDescriptors.add(assocDesc);
                }
            }
            // If there were any Vplex Mirrors, add a descriptors for them.
            addDescriptorsForVplexMirrors(volumeDescriptors, volume);
        }
    }
    return volumeDescriptors;
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume) ArrayList(java.util.ArrayList) URI(java.net.URI)

Example 48 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor 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 49 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VPlexDeviceController method createStepsForFullCopyImport.

/**
 * Creates a step in the passed workflow to import each copy of the passed
 * primary backend volume to a VPLEX virtual volume.
 *
 * @param workflow
 *            A reference to the workflow.
 * @param vplexURI
 *            The URI of the VPLEX storage system.
 * @param sourceBlockObject
 *            The primary backend volume/snapshot that was copied.
 * @param vplexVolumeDescriptors
 *            The volume descriptors representing the
 *            copies of the VPLEX volume.
 * @param assocVolumeDescriptors
 *            The volume descriptors representing the
 *            primary copies and, for copies of distributed VPLEX volumes, the
 *            newly created HA volumes. These volumes will comprise the backend
 *            volumes of the VPLEX volume copies.
 * @param waitFor
 *            The step in to workflow for which these steps should wait
 *            to successfully complete before executing.
 *
 * @return The step for which any subsequent steps in the workflow should
 *         wait.
 */
private String createStepsForFullCopyImport(Workflow workflow, URI vplexURI, List<VolumeDescriptor> vplexVolumeDescriptors, List<VolumeDescriptor> assocVolumeDescriptors, String waitFor) {
    StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
    _log.info("Got VPLEX {}", vplexURI);
    URI projectURI = null;
    URI tenantURI = null;
    Operation op = new Operation();
    op.setResourceType(ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME);
    for (VolumeDescriptor vplexVolumeDescriptor : vplexVolumeDescriptors) {
        _log.info("Creating step for VPLEX volume copy {}", vplexVolumeDescriptor.getVolumeURI());
        List<VolumeDescriptor> descriptorsForImport = new ArrayList<VolumeDescriptor>();
        descriptorsForImport.add(vplexVolumeDescriptor);
        URI vplexVolumeURI = vplexVolumeDescriptor.getVolumeURI();
        List<VolumeDescriptor> assocDescriptors = getDescriptorsForAssociatedVolumes(vplexVolumeURI, assocVolumeDescriptors);
        descriptorsForImport.addAll(assocDescriptors);
        // get the project and tenant from the vplex volume
        if (projectURI == null) {
            Volume vplexVol = _dbClient.queryObject(Volume.class, vplexVolumeURI);
            if (vplexVol != null && !vplexVol.getInactive()) {
                projectURI = vplexVol.getProject().getURI();
                tenantURI = vplexVol.getTenant().getURI();
            }
        }
        _log.info("Added descriptors for the copy's associated volumes");
        String stepId = workflow.createStepId();
        Workflow.Method executeMethod = createImportCopyMethod(vplexURI, descriptorsForImport, projectURI, tenantURI);
        Workflow.Method rollbackMethod = rollbackImportCopyMethod(vplexVolumeDescriptor, assocDescriptors);
        workflow.createStep(IMPORT_COPY_STEP, String.format("Importing copied volume to create VPLEX volume %s", vplexVolumeDescriptor.getVolumeURI()), waitFor, vplexURI, vplexSystem.getSystemType(), this.getClass(), executeMethod, rollbackMethod, stepId);
        _log.info("Added import workflow step to create VPLEX volume copy");
        // be updated when the step is executed and completed.
        for (VolumeDescriptor assocDescriptor : assocDescriptors) {
            if (assocDescriptor.getType().equals(VolumeDescriptor.Type.BLOCK_DATA)) {
                op = _dbClient.createTaskOpStatus(Volume.class, assocDescriptor.getVolumeURI(), stepId, op);
            }
        }
    }
    return IMPORT_COPY_STEP;
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) Operation(com.emc.storageos.db.client.model.Operation) ExportOperationContextOperation(com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 50 with VolumeDescriptor

use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.

the class VPlexDeviceController method addStepsForPostDeleteVolumes.

/**
 * Add step to Workflow for post - delete clean of Virtual Volumes (i.e. marking them inactive).
 *
 * @param workflow
 *            -- Workflow
 * @param waitFor
 *            -- String waitFor of previous step, we wait on this to complete
 * @param volumes
 *            -- List of VolumeDescriptors
 * @param taskId
 *            -- String overall task id.
 * @param completer
 *            -- VolumeWorkflowCompleter
 * @return -- Returns waitFor of next step
 */
@Override
public String addStepsForPostDeleteVolumes(Workflow workflow, String waitFor, List<VolumeDescriptor> volumes, String taskId, VolumeWorkflowCompleter completer) {
    // Filter to get only the VPlex volumes.
    List<VolumeDescriptor> vplexVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
    // Check to see if there are any volumes flagged to not be fully deleted.
    // Any flagged volumes will be removed from the list of volumes to delete.
    List<VolumeDescriptor> descriptorsToRemove = VolumeDescriptor.getDoNotDeleteDescriptors(vplexVolumes);
    vplexVolumes.removeAll(descriptorsToRemove);
    String returnWaitFor = waitFor;
    // If there are no VPlex volumes, just return
    if (vplexVolumes.isEmpty()) {
        return returnWaitFor;
    }
    // Segregate by device and loop over each VPLEX system.
    // Sort the volumes by its system, and consistency group
    Map<URI, Set<URI>> cgVolsMap = new HashMap<URI, Set<URI>>();
    // Keep a separate map for determining if we should delete the VPLEX CG as part of the delete operation.
    Map<URI, Set<URI>> cgVolsWithBackingVolsMap = new HashMap<URI, Set<URI>>();
    Map<URI, List<VolumeDescriptor>> vplexMap = VolumeDescriptor.getDeviceMap(vplexVolumes);
    for (URI vplexURI : vplexMap.keySet()) {
        List<URI> vplexVolumeURIs = VolumeDescriptor.getVolumeURIs(vplexMap.get(vplexURI));
        List<URI> forgetVolumeURIs = new ArrayList<URI>();
        for (URI vplexVolumeURI : vplexVolumeURIs) {
            Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
            boolean inCG = false;
            if (!NullColumnValueGetter.isNullURI(vplexVolume.getConsistencyGroup())) {
                inCG = true;
            }
            if (null == vplexVolume.getAssociatedVolumes()) {
                _log.warn("VPLEX volume {} has no backend volumes. It was possibly ingested 'Virtual Volume Only'.", vplexVolume.forDisplay());
            } else {
                for (String forgetVolumeId : vplexVolume.getAssociatedVolumes()) {
                    forgetVolumeURIs.add(URI.create(forgetVolumeId));
                }
            }
            if (inCG) {
                Set<URI> cgVols = cgVolsMap.get(vplexVolume.getConsistencyGroup());
                if (cgVols == null) {
                    cgVolsMap.put(vplexVolume.getConsistencyGroup(), new HashSet<>());
                    cgVolsWithBackingVolsMap.put(vplexVolume.getConsistencyGroup(), new HashSet<>());
                }
                cgVolsMap.get(vplexVolume.getConsistencyGroup()).add(vplexVolumeURI);
                cgVolsWithBackingVolsMap.get(vplexVolume.getConsistencyGroup()).add(vplexVolumeURI);
                cgVolsWithBackingVolsMap.get(vplexVolume.getConsistencyGroup()).addAll(forgetVolumeURIs);
            }
            // Adding the VPLEX mirror backend volume to forgetVolumeURIs
            if (vplexVolume.getMirrors() != null && !(vplexVolume.getMirrors().isEmpty())) {
                for (String mirrorId : vplexVolume.getMirrors()) {
                    VplexMirror vplexMirror = _dbClient.queryObject(VplexMirror.class, URI.create(mirrorId));
                    if (null != vplexMirror && !vplexMirror.getInactive() && null != vplexMirror.getAssociatedVolumes()) {
                        for (String forgetVolumeId : vplexMirror.getAssociatedVolumes()) {
                            forgetVolumeURIs.add(URI.create(forgetVolumeId));
                        }
                    }
                }
            }
        }
        // Add a step to forget the backend volumes for the deleted
        // VPLEX volumes on this VPLEX system.
        addStepToForgetVolumes(workflow, vplexURI, forgetVolumeURIs, returnWaitFor);
    }
    // Get the VPlex Volume URIs and any VPLEX system URI. It does not matter which
    // system as it the step simply marks ViPR volumes in the database inactive.
    List<URI> allVplexVolumeURIs = VolumeDescriptor.getVolumeURIs(vplexVolumes);
    URI vplexURI = vplexVolumes.get(0).getDeviceURI();
    // Add a step to the Workflow to mark the Virtual Volumes inactive.
    // Rollback does the same thing.
    returnWaitFor = workflow.createStep(null, "Mark virtual volumes inactive", VOLUME_FORGET_STEP, vplexURI, DiscoveredDataObject.Type.vplex.name(), this.getClass(), markVolumesInactiveMethod(allVplexVolumeURIs), markVolumesInactiveMethod(allVplexVolumeURIs), null);
    if (cgVolsMap.isEmpty()) {
        return returnWaitFor;
    }
    Volume vol = getDataObject(Volume.class, allVplexVolumeURIs.get(0), _dbClient);
    ConsistencyGroupManager consistencyGroupManager = getConsistencyGroupManager(vol);
    // Generate step(s) to delete the VPLEX consistency groups
    for (URI cgURI : cgVolsMap.keySet()) {
        // Skip volumes that are part of a VPlex SRDF target CG, as it will
        // be deleted earlier
        List<URI> volURIs = new ArrayList<URI>(cgVolsMap.get(cgURI));
        volURIs = VPlexSrdfUtil.filterOutVplexSrdfTargets(_dbClient, volURIs);
        if (volURIs.isEmpty()) {
            _log.info(String.format("CG %s has all VPLEX SRDF targets, skipping as CG should already be deleted", cgURI));
            continue;
        }
        // find member volumes in the group
        volURIs = new ArrayList<URI>(cgVolsWithBackingVolsMap.get(cgURI));
        Volume firstVol = _dbClient.queryObject(Volume.class, volURIs.get(0));
        URI storage = firstVol.getStorageController();
        // delete CG from array
        if (VPlexUtil.cgHasNoOtherVPlexVolumes(_dbClient, cgURI, volURIs)) {
            _log.info(String.format("Adding step to delete the consistency group %s", cgURI));
            returnWaitFor = consistencyGroupManager.addStepsForDeleteConsistencyGroup(workflow, returnWaitFor, storage, cgURI, false);
        } else {
            _log.info(String.format("Skipping add step to delete the consistency group %s. Consistency group " + "contains other VPLEX volumes that have not been accounted for.", cgURI));
        }
    }
    return returnWaitFor;
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Set(java.util.Set) HashSet(java.util.HashSet) StringSet(com.emc.storageos.db.client.model.StringSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) Volume(com.emc.storageos.db.client.model.Volume) ApplicationAddVolumeList(com.emc.storageos.volumecontroller.ApplicationAddVolumeList) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) List(java.util.List) VplexMirror(com.emc.storageos.db.client.model.VplexMirror)

Aggregations

VolumeDescriptor (com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor)117 Volume (com.emc.storageos.db.client.model.Volume)98 URI (java.net.URI)86 NamedURI (com.emc.storageos.db.client.model.NamedURI)77 ArrayList (java.util.ArrayList)77 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)38 HashMap (java.util.HashMap)38 StringSet (com.emc.storageos.db.client.model.StringSet)29 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)27 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)19 FCTN_STRING_TO_URI (com.emc.storageos.db.client.util.CommonTransformerFunctions.FCTN_STRING_TO_URI)18 Workflow (com.emc.storageos.workflow.Workflow)18 ApplicationAddVolumeList (com.emc.storageos.volumecontroller.ApplicationAddVolumeList)17 ControllerException (com.emc.storageos.volumecontroller.ControllerException)17 List (java.util.List)17 BlockOrchestrationController (com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationController)16 VirtualPool (com.emc.storageos.db.client.model.VirtualPool)16 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)16 URISyntaxException (java.net.URISyntaxException)16 BlockConsistencyGroup (com.emc.storageos.db.client.model.BlockConsistencyGroup)15