Search in sources :

Example 1 with VplexVolumeIngestionContext

use of com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext in project coprhd-controller by CoprHD.

the class BlockRecoverPointIngestOrchestrator method performRPExportIngestion.

/**
 * RecoverPoint volumes are expected to have export masks where the volume is exported to
 * a RecoverPoint site. Therefore every RP volume (sources, targets, journals) will need to
 * go through this code and have their export mask ingested. Even if the mask has already been
 * ingested by a previous volume ingestion, this method still needs to update the ExportGroup and
 * ExportMask objects to reflect the newly ingested volume as part of its management.
 *
 * @param volumeContext the RecoverPointVolumeIngestionContext for the volume currently being ingested
 * @param unManagedVolume unmanaged volume
 * @param volume managed volume
 * @return managed volume with export ingested
 */
private void performRPExportIngestion(IngestionRequestContext parentRequestContext, RecoverPointVolumeIngestionContext volumeContext, UnManagedVolume unManagedVolume, Volume volume) {
    _logger.info("starting RecoverPoint export ingestion for volume {}", volume.forDisplay());
    Project project = volumeContext.getProject();
    ProtectionSystem protectionSystem = _dbClient.queryObject(ProtectionSystem.class, volume.getProtectionController());
    StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, volume.getStorageController());
    List<UnManagedExportMask> unManagedRPExportMasks = findUnManagedRPExportMask(protectionSystem, unManagedVolume);
    if (unManagedRPExportMasks.isEmpty()) {
        _logger.error("Could not find any unmanaged export masks associated with volume: " + unManagedVolume.getLabel());
        throw IngestionException.exceptions.noUnManagedExportMaskFound(unManagedVolume.getNativeGuid());
    }
    // Keep a map for internal site name name and varray
    Map<String, VirtualArray> internalSiteToVarrayMap = new HashMap<String, VirtualArray>();
    internalSiteToVarrayMap.put(volume.getInternalSiteName(), volumeContext.getVarray(unManagedVolume));
    // If this is a MetroPoint volume we're going to have multiple ExportMasks/ExportGroups to deal with.
    // We'll need to query the backend volumes for extra info to populate internalSiteToVarrayMap so
    // we can properly line up the ExportMasks/ExportGroups.
    boolean metropoint = RPHelper.isMetroPointVolume(_dbClient, volume);
    if (metropoint) {
        // We need the VPLEX ingest context to get the backend volume info
        VplexVolumeIngestionContext vplexVolumeContext = ((RpVplexVolumeIngestionContext) volumeContext.getVolumeContext()).getVplexVolumeIngestionContext();
        for (String associatedVolumeIdStr : vplexVolumeContext.getAssociatedVolumeIds(volume)) {
            // Find the associated volumes using the context maps or the db if they are already there
            Volume associatedVolume = VolumeIngestionUtil.findVolume(_dbClient, vplexVolumeContext.getBlockObjectsToBeCreatedMap(), vplexVolumeContext.getDataObjectsToBeUpdatedMap(), associatedVolumeIdStr);
            String internalSiteName = associatedVolume.getInternalSiteName();
            // If we don't already have an entry for this internal site name, let's add it now.
            if (!internalSiteToVarrayMap.containsKey(internalSiteName)) {
                internalSiteToVarrayMap.put(internalSiteName, _dbClient.queryObject(VirtualArray.class, associatedVolume.getVirtualArray()));
            }
        }
    }
    // this will more than likely only loop once.
    for (Entry<String, VirtualArray> entry : internalSiteToVarrayMap.entrySet()) {
        String internalSiteName = entry.getKey();
        VirtualArray virtualArray = entry.getValue();
        UnManagedExportMask em = null;
        if (metropoint) {
            // Since we're flagged for MetroPoint we need to determine which ExportMask to use.
            // We need the MetroPoint volume to be added to BOTH ExportGroups that represent the
            // two Storage Views on VPLEX for cluster-1 and cluster-2.
            // So let's use the varray to find the cluster we're looking for on this pass and match
            // it to the maskingViewParth of the UnManagedExportMask.
            // This should line things up roughly as:
            // VPLEX Storage View 1 -> VPLEX Cluster1 + RPA1
            // VPLEX Storage View 2 -> VPLEX Cluster2 + RPA2
            String vplexCluster = ConnectivityUtil.getVplexClusterForVarray(virtualArray.getId(), storageSystem.getId(), _dbClient);
            // First try and match based on UnManagedExportMask ports
            for (UnManagedExportMask exportMask : unManagedRPExportMasks) {
                for (String portUri : exportMask.getKnownStoragePortUris()) {
                    StoragePort port = _dbClient.queryObject(StoragePort.class, URI.create(portUri));
                    if (port != null && !port.getInactive()) {
                        String vplexClusterForMask = ConnectivityUtil.getVplexClusterOfPort(port);
                        if (vplexCluster.equals(vplexClusterForMask)) {
                            em = exportMask;
                            break;
                        }
                    }
                }
                if (em != null) {
                    break;
                }
            }
            if (em == null) {
                // It really shouldn't come to this, but leaving this code just in case.
                for (UnManagedExportMask exportMask : unManagedRPExportMasks) {
                    if (exportMask.getMaskingViewPath().contains("cluster-" + vplexCluster)) {
                        em = exportMask;
                        break;
                    }
                }
            }
        } else {
            em = unManagedRPExportMasks.get(0);
        }
        // If the mask for ingested volume is in a mask that contains JOURNAL keyword, make sure the ExportGroup created contains
        // that internal flag.
        boolean isJournalExport = false;
        if (em.getMaskName().toLowerCase().contains(VolumeIngestionUtil.RP_JOURNAL)) {
            isJournalExport = true;
        }
        String exportGroupGeneratedName = RPHelper.generateExportGroupName(protectionSystem, storageSystem, internalSiteName, virtualArray, isJournalExport);
        ExportGroup exportGroup = VolumeIngestionUtil.verifyExportGroupExists(parentRequestContext, exportGroupGeneratedName, project.getId(), em.getKnownInitiatorUris(), virtualArray.getId(), _dbClient);
        boolean exportGroupCreated = false;
        if (null == exportGroup) {
            exportGroupCreated = true;
            Integer numPaths = em.getZoningMap().size();
            _logger.info("Creating Export Group with label {}", em.getMaskName());
            exportGroup = RPHelper.createRPExportGroup(exportGroupGeneratedName, virtualArray, project, numPaths, isJournalExport);
        }
        if (null != exportGroup) {
            // check if the ExportGroup has already been fetched
            ExportGroup loadedExportGroup = parentRequestContext.findExportGroup(exportGroup.getLabel(), project.getId(), virtualArray.getId(), null, null);
            if (null != loadedExportGroup) {
                exportGroup = loadedExportGroup;
            }
        }
        volumeContext.setExportGroup(exportGroup);
        volumeContext.setExportGroupCreated(exportGroupCreated);
        volumeContext.getRpExportGroupMap().put(exportGroup, exportGroupCreated);
        // set RP device initiators to be used as the "host" for export mask ingestion
        List<Initiator> initiators = new ArrayList<Initiator>();
        Iterator<Initiator> initiatorItr = _dbClient.queryIterativeObjects(Initiator.class, URIUtil.toURIList(em.getKnownInitiatorUris()));
        while (initiatorItr.hasNext()) {
            initiators.add(initiatorItr.next());
        }
        volumeContext.setDeviceInitiators(initiators);
        // find the ingest export strategy and call into for this unmanaged export mask
        IngestExportStrategy ingestStrategy = ingestStrategyFactory.buildIngestExportStrategy(unManagedVolume);
        volume = ingestStrategy.ingestExportMasks(unManagedVolume, volume, volumeContext);
        if (null == volume) {
            // ingestion did not succeed, but in case it wasn't, throw one
            throw IngestionException.exceptions.generalVolumeException(unManagedVolume.getLabel(), "check the logs for more details");
        }
    }
}
Also used : VirtualArray(com.emc.storageos.db.client.model.VirtualArray) HashMap(java.util.HashMap) VplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) StoragePort(com.emc.storageos.db.client.model.StoragePort) ArrayList(java.util.ArrayList) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem) Project(com.emc.storageos.db.client.model.Project) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) Volume(com.emc.storageos.db.client.model.Volume) Initiator(com.emc.storageos.db.client.model.Initiator) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) StorageSystem(com.emc.storageos.db.client.model.StorageSystem) UnManagedExportMask(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask)

Example 2 with VplexVolumeIngestionContext

use of com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext in project coprhd-controller by CoprHD.

the class BlockVplexVolumeIngestOrchestrator method ingestBlockObjects.

@Override
public <T extends BlockObject> T ingestBlockObjects(IngestionRequestContext requestContext, Class<T> clazz) throws IngestionException {
    refreshCaches(requestContext.getStorageSystem());
    UnManagedVolume unManagedVolume = requestContext.getCurrentUnmanagedVolume();
    VolumeIngestionUtil.checkValidVarrayForUnmanagedVolume(unManagedVolume, requestContext.getVarray(unManagedVolume).getId(), getClusterIdToNameMap(requestContext.getStorageSystem()), getVarrayToClusterIdMap(requestContext.getStorageSystem()), _dbClient);
    String vplexIngestionMethod = requestContext.getVplexIngestionMethod();
    _logger.info("VPLEX ingestion method is " + vplexIngestionMethod);
    boolean ingestBackend = (null == vplexIngestionMethod) || vplexIngestionMethod.isEmpty() || (!vplexIngestionMethod.equals(VplexBackendIngestionContext.INGESTION_METHOD_VVOL_ONLY));
    VplexVolumeIngestionContext volumeContext = null;
    boolean isRpVplexContext = requestContext.getVolumeContext() instanceof RpVplexVolumeIngestionContext;
    if (isRpVplexContext) {
        // if this volume is RP/VPLEX, we need to get the volume context
        // from the RpVplexVolumeIngestionContext
        volumeContext = ((RpVplexVolumeIngestionContext) requestContext.getVolumeContext()).getVplexVolumeIngestionContext();
    } else {
        // this is just a plain VPLEX volume backend ingestion
        volumeContext = (VplexVolumeIngestionContext) requestContext.getVolumeContext();
    }
    // set the name of the cluster to which this virtual volume ingestion request's varray is connected
    String clusterName = getClusterNameForVarray(requestContext.getVarray(unManagedVolume), requestContext.getStorageSystem());
    volumeContext.setVirtualVolumeVplexClusterName(clusterName);
    // determine if the backend has already been ingested. this could be the case if the volume is
    // exported via multipe varrays or hosts and needs to be ingested for export multiple times
    String volumeNativeGuid = unManagedVolume.getNativeGuid().replace(VolumeIngestionUtil.UNMANAGEDVOLUME, VolumeIngestionUtil.VOLUME);
    Volume volume = VolumeIngestionUtil.checkIfVolumeExistsInDB(volumeNativeGuid, _dbClient);
    boolean backendAlreadyIngested = volume != null && volume.getAssociatedVolumes() != null && !volume.getAssociatedVolumes().isEmpty();
    if (backendAlreadyIngested) {
        _logger.info("backend volumes have already been ingested for UnManagedVolume {}", unManagedVolume.forDisplay());
    } else if (ingestBackend) {
        volumeContext.setIngestionInProgress(true);
        // 
        // If the "Only During Discovery" system setting is set, no new data will
        // be fetched during ingestion. This assumes that all data has been collected
        // during discovery and ingestion will fail if it can't find all the required data.
        // 
        // If "Only During Ingestion" or "During Discovery and Ingestion" mode is set,
        // then an attempt will be made to query the VPLEX api now to find any incomplete data,
        // but the database will be checked first.
        // 
        // The default mode is "Only During Discovery", so the user needs to remember
        // to run discovery first on all backend storage arrays before running on the VPLEX.
        // 
        _discoveryMode = ControllerUtils.getPropertyValueFromCoordinator(_coordinator, VplexBackendIngestionContext.DISCOVERY_MODE);
        if (VplexBackendIngestionContext.DISCOVERY_MODE_DISCOVERY_ONLY.equals(_discoveryMode) || VplexBackendIngestionContext.DISCOVERY_MODE_DB_ONLY.equals(_discoveryMode)) {
            volumeContext.setInDiscoveryOnlyMode(true);
        }
        // the backend volumes and export masks will be part of the VPLEX project
        // rather than the front-end virtual volume project, so we need to set that in the context
        Project vplexProject = VPlexBlockServiceApiImpl.getVplexProject(requestContext.getStorageSystem(), _dbClient, _tenantsService);
        volumeContext.setBackendProject(vplexProject);
        volumeContext.setFrontendProject(requestContext.getProject());
        try {
            _logger.info("Ingesting backend structure of VPLEX virtual volume {}", unManagedVolume.getLabel());
            validateContext(requestContext.getVpool(unManagedVolume), requestContext.getTenant(), volumeContext);
            ingestBackendVolumes(requestContext, volumeContext);
            ingestBackendExportMasks(requestContext, volumeContext);
            _logger.info("Backend ingestion ended:" + volumeContext.toStringDebug());
        } catch (Exception ex) {
            _logger.error("error during VPLEX backend ingestion: ", ex);
            throw IngestionException.exceptions.failedToIngestVplexBackend(ex.getLocalizedMessage());
        }
    }
    _logger.info("Ingesting VPLEX virtual volume {}", unManagedVolume.getLabel());
    T virtualVolume = super.ingestBlockObjects(requestContext, clazz);
    return virtualVolume;
}
Also used : Project(com.emc.storageos.db.client.model.Project) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) Volume(com.emc.storageos.db.client.model.Volume) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) VplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext)

Example 3 with VplexVolumeIngestionContext

use of com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext in project coprhd-controller by CoprHD.

the class BlockVolumeIngestOrchestrator method ingestBlockObjects.

@Override
protected <T extends BlockObject> T ingestBlockObjects(IngestionRequestContext requestContext, Class<T> clazz) throws IngestionException {
    UnManagedVolume unManagedVolume = requestContext.getCurrentUnmanagedVolume();
    boolean unManagedVolumeExported = requestContext.getVolumeContext().isVolumeExported();
    Volume volume = null;
    List<BlockSnapshotSession> snapSessions = new ArrayList<BlockSnapshotSession>();
    URI unManagedVolumeUri = unManagedVolume.getId();
    String volumeNativeGuid = unManagedVolume.getNativeGuid().replace(VolumeIngestionUtil.UNMANAGEDVOLUME, VolumeIngestionUtil.VOLUME);
    volume = VolumeIngestionUtil.checkIfVolumeExistsInDB(volumeNativeGuid, _dbClient);
    // Check if ingested volume has export masks pending for ingestion.
    if (isExportIngestionPending(volume, unManagedVolumeUri, unManagedVolumeExported)) {
        return clazz.cast(volume);
    }
    if (null == volume) {
        validateUnManagedVolume(unManagedVolume, requestContext.getVpool(unManagedVolume));
        // @TODO Need to revisit this. In 8.x Provider, ReplicationGroup is automatically created when a volume is associated to a
        // StorageGroup.
        // checkUnManagedVolumeAddedToCG(unManagedVolume, virtualArray, tenant, project, vPool);
        checkVolumeExportState(unManagedVolume, unManagedVolumeExported);
        checkVPoolValidForExportInitiatorProtocols(requestContext.getVpool(unManagedVolume), unManagedVolume);
        checkHostIOLimits(requestContext.getVpool(unManagedVolume), unManagedVolume, unManagedVolumeExported);
        StoragePool pool = validateAndReturnStoragePoolInVAarray(unManagedVolume, requestContext.getVarray(unManagedVolume));
        // validate quota is exceeded for storage systems and pools
        checkSystemResourceLimitsExceeded(requestContext.getStorageSystem(), unManagedVolume, requestContext.getExhaustedStorageSystems());
        checkPoolResourceLimitsExceeded(requestContext.getStorageSystem(), pool, unManagedVolume, requestContext.getExhaustedPools());
        String autoTierPolicyId = getAutoTierPolicy(unManagedVolume, requestContext.getStorageSystem(), requestContext.getVpool(unManagedVolume));
        validateAutoTierPolicy(autoTierPolicyId, unManagedVolume, requestContext.getVpool(unManagedVolume));
        volume = createVolume(requestContext, volumeNativeGuid, pool, unManagedVolume, autoTierPolicyId);
    }
    if (volume != null) {
        String syncActive = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.IS_SYNC_ACTIVE.toString(), unManagedVolume.getVolumeInformation());
        boolean isSyncActive = (null != syncActive) ? Boolean.parseBoolean(syncActive) : false;
        volume.setSyncActive(isSyncActive);
        if (VolumeIngestionUtil.isFullCopy(unManagedVolume)) {
            _logger.info("Setting clone related properties {}", unManagedVolume.getId());
            String replicaState = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.REPLICA_STATE.toString(), unManagedVolume.getVolumeInformation());
            volume.setReplicaState(replicaState);
            String replicationGroupName = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.FULL_COPY_CONSISTENCY_GROUP_NAME.toString(), unManagedVolume.getVolumeInformation());
            if (replicationGroupName != null && !replicationGroupName.isEmpty()) {
                volume.setReplicationGroupInstance(replicationGroupName);
            }
        }
        // Create snapshot sessions for each synchronization aspect for the volume.
        StringSet syncAspectInfoForVolume = PropertySetterUtil.extractValuesFromStringSet(SupportedVolumeInformation.SNAPSHOT_SESSIONS.toString(), unManagedVolume.getVolumeInformation());
        if ((syncAspectInfoForVolume != null) && (!syncAspectInfoForVolume.isEmpty())) {
            Project project = requestContext.getProject();
            // If this is a vplex backend volume, then the front end project should be set as snapshot session's project
            if (requestContext instanceof VplexVolumeIngestionContext && VolumeIngestionUtil.isVplexBackendVolume(unManagedVolume)) {
                project = ((VplexVolumeIngestionContext) requestContext).getFrontendProject();
            }
            for (String syncAspectInfo : syncAspectInfoForVolume) {
                String[] syncAspectInfoComponents = syncAspectInfo.split(":");
                String syncAspectName = syncAspectInfoComponents[0];
                String syncAspectObjPath = syncAspectInfoComponents[1];
                // Make sure it is not already created.
                URIQueryResultList queryResults = new URIQueryResultList();
                _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getBlockSnapshotSessionBySessionInstance(syncAspectObjPath), queryResults);
                Iterator<URI> queryResultsIter = queryResults.iterator();
                if (!queryResultsIter.hasNext()) {
                    BlockSnapshotSession session = new BlockSnapshotSession();
                    session.setId(URIUtil.createId(BlockSnapshotSession.class));
                    session.setLabel(syncAspectName);
                    session.setSessionLabel(syncAspectName);
                    session.setParent(new NamedURI(volume.getId(), volume.getLabel()));
                    session.setProject(new NamedURI(project.getId(), project.getLabel()));
                    session.setStorageController(volume.getStorageController());
                    session.setSessionInstance(syncAspectObjPath);
                    StringSet linkedTargetURIs = new StringSet();
                    URIQueryResultList snapshotQueryResults = new URIQueryResultList();
                    _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getBlockSnapshotBySettingsInstance(syncAspectObjPath), snapshotQueryResults);
                    Iterator<URI> snapshotQueryResultsIter = snapshotQueryResults.iterator();
                    while (snapshotQueryResultsIter.hasNext()) {
                        linkedTargetURIs.add(snapshotQueryResultsIter.next().toString());
                    }
                    session.setLinkedTargets(linkedTargetURIs);
                    session.setOpStatus(new OpStatusMap());
                    snapSessions.add(session);
                }
            }
            if (!snapSessions.isEmpty()) {
                _dbClient.createObject(snapSessions);
            }
        }
    }
    // Note that a VPLEX backend volume can also be a snapshot target volume.
    // When the VPLEX ingest orchestrator is executed, it gets the ingestion
    // strategy for the backend volume and executes it. If the backend volume
    // is both a snapshot and a VPLEX backend volume, this local volume ingest
    // strategy is invoked and a Volume instance will result. That is fine because
    // we need to represent that VPLEX backend volume. However, we also need a
    // BlockSnapshot instance to represent the snapshot target volume. Therefore,
    // if the unmanaged volume is also a snapshot target volume, we get and
    // execute the local snapshot ingest strategy to create this BlockSnapshot
    // instance and we add it to the created object list. Note that since the
    // BlockSnapshot is added to the created objects list and the Volume and
    // BlockSnapshot instance will have the same native GUID, we must be careful
    // about adding the Volume to the created object list in the VPLEX ingestion
    // strategy.
    BlockObject snapshot = null;
    if (VolumeIngestionUtil.isSnapshot(unManagedVolume)) {
        String strategyKey = ReplicationStrategy.LOCAL.name() + "_" + VolumeType.SNAPSHOT.name();
        IngestStrategy ingestStrategy = ingestStrategyFactory.getIngestStrategy(IngestStrategyEnum.getIngestStrategy(strategyKey));
        snapshot = ingestStrategy.ingestBlockObjects(requestContext, BlockSnapshot.class);
        requestContext.getBlockObjectsToBeCreatedMap().put(snapshot.getNativeGuid(), snapshot);
    }
    // Run this always when volume NO_PUBLIC_ACCESS
    if (markUnManagedVolumeInactive(requestContext, volume)) {
        _logger.info("All the related replicas and parent has been ingested ", unManagedVolume.getNativeGuid());
        // RP masks.
        if (!unManagedVolumeExported && !VolumeIngestionUtil.checkUnManagedResourceIsRecoverPointEnabled(unManagedVolume)) {
            unManagedVolume.setInactive(true);
            requestContext.getUnManagedVolumesToBeDeleted().add(unManagedVolume);
        }
    } else if (volume != null) {
        _logger.info("Not all the parent/replicas of unManagedVolume {} have been ingested , hence marking as internal", unManagedVolume.getNativeGuid());
        volume.addInternalFlags(INTERNAL_VOLUME_FLAGS);
        for (BlockSnapshotSession snapSession : snapSessions) {
            snapSession.addInternalFlags(INTERNAL_VOLUME_FLAGS);
        }
        _dbClient.updateObject(snapSessions);
    }
    return clazz.cast(volume);
}
Also used : StoragePool(com.emc.storageos.db.client.model.StoragePool) BlockSnapshotSession(com.emc.storageos.db.client.model.BlockSnapshotSession) NamedURI(com.emc.storageos.db.client.model.NamedURI) VplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext) ArrayList(java.util.ArrayList) OpStatusMap(com.emc.storageos.db.client.model.OpStatusMap) BlockSnapshot(com.emc.storageos.db.client.model.BlockSnapshot) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) Project(com.emc.storageos.db.client.model.Project) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) Volume(com.emc.storageos.db.client.model.Volume) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) StringSet(com.emc.storageos.db.client.model.StringSet) BlockObject(com.emc.storageos.db.client.model.BlockObject)

Example 4 with VplexVolumeIngestionContext

use of com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext in project coprhd-controller by CoprHD.

the class BlockVplexVolumeIngestOrchestrator method ingestBackendExportMasks.

/**
 * Ingests the export masks between the backend storage arrays and the
 * VPLEX for the backend storage volumes.
 *
 * Calls ingestExportMasks by getting a nested IngestStrategy
 * for each backend volume or replica from the IngestStrategyFactory.
 *
 * @param system the VPLEX storage system
 * @param vPool the virtual pool for ingestion
 * @param virtualArray the virtual array for ingestion
 * @param tenant the tenant for ingestion
 * @param unManagedVolumesToBeDeleted unmanaged volumes that will be marked for deletion
 * @param taskStatusMap a map of task statuses
 * @param context the VplexBackendIngestionContext for the parent virtual volume
 *
 * @throws IngestionException
 */
private void ingestBackendExportMasks(IngestionRequestContext requestContext, VplexVolumeIngestionContext backendRequestContext) throws IngestionException {
    // process masking for any successfully processed UnManagedVolumes
    for (Entry<String, VolumeIngestionContext> entry : backendRequestContext.getProcessedUnManagedVolumeMap().entrySet()) {
        String unManagedVolumeGUID = entry.getKey();
        VolumeIngestionContext volumeContext = entry.getValue();
        UnManagedVolume processedUnManagedVolume = volumeContext.getUnmanagedVolume();
        VirtualArray virtualArray = backendRequestContext.getVarray(processedUnManagedVolume);
        VirtualPool vPool = backendRequestContext.getVpool(processedUnManagedVolume);
        if (processedUnManagedVolume.getUnmanagedExportMasks().isEmpty()) {
            String reason = "the backend volume has no unmanaged export masks " + processedUnManagedVolume.getLabel();
            _logger.warn(reason);
            continue;
        }
        _logger.info("ingesting VPLEX backend export mask(s) for unmanaged volume " + processedUnManagedVolume);
        String createdObjectGuid = unManagedVolumeGUID.replace(VolumeIngestionUtil.UNMANAGEDVOLUME, VolumeIngestionUtil.VOLUME);
        BlockObject processedBlockObject = backendRequestContext.getBlockObjectsToBeCreatedMap().get(createdObjectGuid);
        if (processedBlockObject == null) {
            String reason = "The ingested block object is null. Skipping ingestion of export masks.";
            throw IngestionException.exceptions.generalVolumeException(processedUnManagedVolume.getLabel(), reason);
        }
        // and it will have the correct virtual array and virtual pool already set on it
        if (backendRequestContext.isDistributed()) {
            // a backend volume can only be a Volume BlockObject type, so this is safe
            Volume backendVolume = ((Volume) processedBlockObject);
            virtualArray = _dbClient.queryObject(VirtualArray.class, backendVolume.getVirtualArray());
            vPool = _dbClient.queryObject(VirtualPool.class, backendVolume.getVirtualPool());
            if (virtualArray == null) {
                throw IngestionException.exceptions.failedToIngestVplexBackend("Could not find virtual array for backend volume " + backendVolume.getLabel());
            }
            if (vPool == null) {
                throw IngestionException.exceptions.failedToIngestVplexBackend("Could not find virtual pool for backend volume " + backendVolume.getLabel());
            }
        }
        try {
            // assuming only one export mask for this volume between the backend array and VPLEX
            int uemCount = 0;
            for (String uri : processedUnManagedVolume.getUnmanagedExportMasks()) {
                if (uemCount++ > 1) {
                    _logger.warn("more than one unmanaged export mask found on this backend volume");
                }
                UnManagedExportMask uem = _dbClient.queryObject(UnManagedExportMask.class, URI.create(uri));
                _logger.info("preparing to ingest backend unmanaged export mask {}", uem.getMaskName());
                // find the associated storage system
                URI storageSystemUri = processedUnManagedVolume.getStorageSystemUri();
                StorageSystem associatedSystem = _dbClient.queryObject(StorageSystem.class, storageSystemUri);
                // collect the initiators in this backend mask
                List<URI> initUris = new ArrayList<URI>();
                for (String initUri : uem.getKnownInitiatorUris()) {
                    initUris.add(URI.create(initUri));
                }
                List<Initiator> initiators = _dbClient.queryObject(Initiator.class, initUris);
                backendRequestContext.setDeviceInitiators(initiators);
                // find or create the backend export group
                ExportGroup exportGroup = this.findOrCreateExportGroup(backendRequestContext.getRootIngestionRequestContext(), associatedSystem, initiators, virtualArray.getId(), backendRequestContext.getBackendProject().getId(), backendRequestContext.getTenant().getId(), DEFAULT_BACKEND_NUMPATHS, uem);
                if (null == exportGroup.getId()) {
                    backendRequestContext.setExportGroupCreated(true);
                    exportGroup.setId(URIUtil.createId(ExportGroup.class));
                }
                backendRequestContext.setExportGroup(exportGroup);
                // find the ingest export strategy and call into for this unmanaged export mask
                IngestExportStrategy ingestStrategy = ingestStrategyFactory.buildIngestExportStrategy(processedUnManagedVolume);
                BlockObject blockObject = ingestStrategy.ingestExportMasks(processedUnManagedVolume, processedBlockObject, backendRequestContext);
                if (null == blockObject) {
                    // ingestion did not succeed, but in case it wasn't, throw one
                    throw IngestionException.exceptions.generalVolumeException(processedUnManagedVolume.getLabel(), "check the logs for more details");
                } else {
                    backendRequestContext.getObjectsIngestedByExportProcessing().add(blockObject);
                }
                backendRequestContext.getVplexBackendExportGroupMap().put(blockObject, exportGroup);
            }
        } catch (Exception ex) {
            _logger.error(ex.getLocalizedMessage());
            throw ex;
        }
    }
}
Also used : VirtualArray(com.emc.storageos.db.client.model.VirtualArray) ArrayList(java.util.ArrayList) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) PrefixConstraint(com.emc.storageos.db.client.constraint.PrefixConstraint) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) Volume(com.emc.storageos.db.client.model.Volume) Initiator(com.emc.storageos.db.client.model.Initiator) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) VplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext) VolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.VolumeIngestionContext) BlockObject(com.emc.storageos.db.client.model.BlockObject) UnManagedExportMask(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 5 with VplexVolumeIngestionContext

use of com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext in project coprhd-controller by CoprHD.

the class BlockRecoverPointIngestOrchestrator method decorateUpdatesForRPSource.

/**
 * Perform updates of the managed volume and associated unmanaged volumes and protection sets
 * given an RP source volume getting ingested.
 *
 * @param volumeContext the RecoverPointVolumeIngestionContext for the volume currently being ingested
 * @param volume managed volume
 * @param unManagedVolume unmanaged volume
 */
private void decorateUpdatesForRPSource(RecoverPointVolumeIngestionContext volumeContext, Volume volume, UnManagedVolume unManagedVolume) {
    StringSetMap unManagedVolumeInformation = unManagedVolume.getVolumeInformation();
    volume.setPersonality(PersonalityTypes.SOURCE.toString());
    volume.setAccessState(Volume.VolumeAccessState.READWRITE.toString());
    volume.setLinkStatus(Volume.LinkStatus.IN_SYNC.toString());
    // For RP+VPLEX Distributed and MetroPoint volumes, we want to set the
    // internal site and copy names on the backing volumes. This helps when identifying
    // which Export Groups the volume belongs to on the VPLEX.
    // 
    // For MetroPoint, the same VPLEX Distributed/Metro volume will be exported to
    // two VPLEX Export Groups (aka Storage Views). One for each RPA Cluster in the
    // MetroPoint configuration.
    boolean isVPlexDistributedVolume = false;
    if (volumeContext.getVolumeContext() instanceof RpVplexVolumeIngestionContext) {
        VplexVolumeIngestionContext vplexVolumeContext = ((RpVplexVolumeIngestionContext) volumeContext.getVolumeContext()).getVplexVolumeIngestionContext();
        isVPlexDistributedVolume = vplexVolumeContext.getAssociatedVolumeIds(volume).size() > 1;
    }
    if (isVPlexDistributedVolume) {
        // Get the internal site and copy names
        String rpInternalSiteName = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.RP_INTERNAL_SITENAME.toString(), unManagedVolumeInformation);
        String rpCopyName = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.RP_COPY_NAME.toString(), unManagedVolumeInformation);
        String rpStandbyInternalSiteName = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.RP_STANDBY_INTERNAL_SITENAME.toString(), unManagedVolumeInformation);
        String rpStandbyCopyName = PropertySetterUtil.extractValueFromStringSet(SupportedVolumeInformation.RP_STANDBY_COPY_NAME.toString(), unManagedVolumeInformation);
        // We need the VPLEX ingest context to get the backend volume info
        VplexVolumeIngestionContext vplexVolumeContext = ((RpVplexVolumeIngestionContext) volumeContext.getVolumeContext()).getVplexVolumeIngestionContext();
        // Non-matching varrays will be the VPLEX HA side.
        for (String associatedVolumeIdStr : vplexVolumeContext.getAssociatedVolumeIds(volume)) {
            // Find the associated volumes using the context maps or the db if they are already there
            Volume associatedVolume = VolumeIngestionUtil.findVolume(_dbClient, vplexVolumeContext.getBlockObjectsToBeCreatedMap(), vplexVolumeContext.getDataObjectsToBeUpdatedMap(), associatedVolumeIdStr);
            // If we can't get the a handle on the associated volume we'll have to throw an exception
            if (associatedVolume == null) {
                _logger.error("Could not find associated volume: " + associatedVolumeIdStr + " in DB.  Ingestion failed.");
                throw IngestionException.exceptions.generalVolumeException(unManagedVolume.getNativeGuid(), "Could not find associated volume: " + associatedVolumeIdStr + ", for VPLEX volume: " + volume.getLabel());
            }
            // Compare the varrays for the associated volume and its VPLEX virtual volume
            if (associatedVolume.getVirtualArray().equals(volume.getVirtualArray())) {
                associatedVolume.setInternalSiteName(rpInternalSiteName);
                associatedVolume.setRpCopyName(rpCopyName);
            } else {
                // If this is a RP+VPLEX Distributed volume (not MP) there is the potential that
                // rpStandbyInternalSiteName and rpStandbyCopyName could be null, which is fine.
                associatedVolume.setInternalSiteName(rpStandbyInternalSiteName);
                associatedVolume.setRpCopyName(rpStandbyCopyName);
            }
        }
    }
    // When we ingest a source volume, we need to properly create the RP Target list for that source,
    // however it is possible that not all (or any) of the RP targets have been ingested yet. Therefore
    // we need to do as much as we can:
    // 
    // 1. Process each managed target volume ID in the unmanaged source volume, add to the managed source volume's RP target list.
    // 2. Go through each unmanaged RP target volume in the unmanaged source volume (before it goes away), add the managed source volume
    // ID.
    // 3. Go through each unmanaged RP target volume in the unmanaged source volume, remove the unmanaged source volume ID.
    // 1. Process each managed target volume ID in the unmanaged source volume, add to the managed source volume's RP target list.
    StringSet rpManagedTargetVolumeIdStrs = PropertySetterUtil.extractValuesFromStringSet(SupportedVolumeInformation.RP_MANAGED_TARGET_VOLUMES.toString(), unManagedVolumeInformation);
    _logger.info("adding managed RecoverPoint targets volumes: " + rpManagedTargetVolumeIdStrs);
    for (String rpManagedTargetVolumeIdStr : rpManagedTargetVolumeIdStrs) {
        // Check to make sure the target volume is legit.
        Volume managedTargetVolume = null;
        BlockObject bo = volumeContext.getRootIngestionRequestContext().findCreatedBlockObject(URI.create(rpManagedTargetVolumeIdStr));
        if (bo != null && bo instanceof Volume) {
            managedTargetVolume = (Volume) bo;
        }
        if (managedTargetVolume == null) {
            _logger.error("Could not find managed target volume: " + rpManagedTargetVolumeIdStr + " in DB.  Ingestion failed.");
            throw IngestionException.exceptions.noManagedTargetVolumeFound(unManagedVolume.getNativeGuid(), rpManagedTargetVolumeIdStr);
        }
        _logger.info("\tadding RecoverPoint target volume {}", managedTargetVolume.forDisplay());
        if (volume.getRpTargets() == null) {
            volume.setRpTargets(new StringSet());
        }
        volume.getRpTargets().add(managedTargetVolume.getId().toString());
    }
    // 2. Go through each unmanaged RP target volume in the unmanaged source volume (before it goes away), add the managed source volume
    // ID.
    // 3. Go through each unmanaged RP target volume in the unmanaged source volume, remove the unmanaged source volume ID.
    StringSet rpUnManagedTargetVolumeIdStrs = PropertySetterUtil.extractValuesFromStringSet(SupportedVolumeInformation.RP_UNMANAGED_TARGET_VOLUMES.toString(), unManagedVolumeInformation);
    _logger.info("updating unmanaged RecoverPoint targets volumes: " + rpUnManagedTargetVolumeIdStrs);
    for (String rpUnManagedTargetVolumeIdStr : rpUnManagedTargetVolumeIdStrs) {
        UnManagedVolume unManagedTargetVolume = _dbClient.queryObject(UnManagedVolume.class, URI.create(rpUnManagedTargetVolumeIdStr));
        if (unManagedTargetVolume == null) {
            _logger.error("Could not find unmanaged target volume: " + rpUnManagedTargetVolumeIdStr + " in DB.  Ingestion failed.");
            throw IngestionException.exceptions.noUnManagedTargetVolumeFound(unManagedVolume.getNativeGuid(), rpUnManagedTargetVolumeIdStr);
        }
        // (2) Add the managed source volume ID to this target that hasn't been ingested yet, so when it IS ingested, we know
        // what RP source it belongs to.
        StringSet rpManagedSourceVolumeId = new StringSet();
        rpManagedSourceVolumeId.add(volume.getId().toString());
        unManagedTargetVolume.putVolumeInfo(SupportedVolumeInformation.RP_MANAGED_SOURCE_VOLUME.toString(), rpManagedSourceVolumeId);
        // (3) Remove the unmanaged source volume ID to this target that is going away as a result of ingestion.
        // This is for completeness. The ID is going away in the DB, so we don't want any references to it anywhere.
        StringSet rpUnManagedSourceVolumeId = new StringSet();
        unManagedTargetVolume.putVolumeInfo(SupportedVolumeInformation.RP_UNMANAGED_SOURCE_VOLUME.toString(), rpUnManagedSourceVolumeId);
        volumeContext.addUnmanagedTargetVolumeToUpdate(unManagedTargetVolume);
    }
}
Also used : StringSetMap(com.emc.storageos.db.client.model.StringSetMap) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) Volume(com.emc.storageos.db.client.model.Volume) VplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) UnManagedVolume(com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume) StringSet(com.emc.storageos.db.client.model.StringSet) RpVplexVolumeIngestionContext(com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext) BlockObject(com.emc.storageos.db.client.model.BlockObject)

Aggregations

VplexVolumeIngestionContext (com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.VplexVolumeIngestionContext)7 RpVplexVolumeIngestionContext (com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RpVplexVolumeIngestionContext)6 UnManagedVolume (com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume)6 Volume (com.emc.storageos.db.client.model.Volume)6 ArrayList (java.util.ArrayList)4 VolumeIngestionContext (com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.VolumeIngestionContext)3 BlockObject (com.emc.storageos.db.client.model.BlockObject)3 Project (com.emc.storageos.db.client.model.Project)3 StringSet (com.emc.storageos.db.client.model.StringSet)3 RecoverPointVolumeIngestionContext (com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.impl.RecoverPointVolumeIngestionContext)2 BlockSnapshot (com.emc.storageos.db.client.model.BlockSnapshot)2 BlockSnapshotSession (com.emc.storageos.db.client.model.BlockSnapshotSession)2 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)2 Initiator (com.emc.storageos.db.client.model.Initiator)2 NamedURI (com.emc.storageos.db.client.model.NamedURI)2 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)2 UnManagedExportMask (com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask)2 VirtualArray (com.emc.storageos.db.client.model.VirtualArray)2 URI (java.net.URI)2 IngestionRequestContext (com.emc.storageos.api.service.impl.resource.blockingestorchestration.context.IngestionRequestContext)1