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");
}
}
}
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;
}
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);
}
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;
}
}
}
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);
}
}
Aggregations