use of com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask in project coprhd-controller by CoprHD.
the class ClusterService method getUnmanagedExportMasks.
/**
* Gets the UnManagedExportMasks found for a Cluster.
*
* @param id the URI of a ViPR Cluster
* @brief List unmanaged export masks for a cluster
* @return a list of UnManagedExportMasks found for the Cluster
* @throws DatabaseException when a database error occurs
*/
@GET
@Path("/{id}/unmanaged-export-masks")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public UnManagedExportMaskList getUnmanagedExportMasks(@PathParam("id") URI id) throws DatabaseException {
Cluster cluster = queryObject(Cluster.class, id, false);
// check the user permissions
verifyAuthorizedInTenantOrg(cluster.getTenant(), getUserFromContext());
// get the unmanaged export masks
List<UnManagedExportMask> uems = VolumeIngestionUtil.findUnManagedExportMasksForCluster(id, _dbClient);
UnManagedExportMaskList list = new UnManagedExportMaskList();
for (UnManagedExportMask uem : uems) {
list.getUnManagedExportMasks().add(toRelatedResource(ResourceTypeEnum.UNMANAGED_EXPORT_MASKS, uem.getId()));
}
return list;
}
use of com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask 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.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask in project coprhd-controller by CoprHD.
the class BlockRecoverPointIngestOrchestrator method findUnManagedRPExportMask.
/**
* This unmanaged volume may be associated with several export masks. We need to find the export mask
* that belongs specifically to the RP protection system supplied.
*
* Note: There could only be more than one mask that contains both the protection system's initiators AND the volume which
* would indicate MetroPoint. In a MetroPoint configuration the VPLEX Distributed Source volume is exported to RP
* via two different Storage Views. One per VPLEX cluster to two different RPA clusters.
*
* @param protectionSystem protection system
* @param unManagedVolume unmanaged volume
* @return unmanaged export masks that belong to the protection system that contains the unmanaged volume
*/
private List<UnManagedExportMask> findUnManagedRPExportMask(ProtectionSystem protectionSystem, UnManagedVolume unManagedVolume) {
List<UnManagedExportMask> unManagedRPExportMasks = new ArrayList<UnManagedExportMask>();
for (String maskIdStr : unManagedVolume.getUnmanagedExportMasks()) {
// Find the mask associated with the protection system.
UnManagedExportMask em = _dbClient.queryObject(UnManagedExportMask.class, URI.create(maskIdStr));
if (em == null) {
_logger.error("UnManagedExportMask with ID: " + maskIdStr + " could not be found in DB. Could already be ingested.");
continue;
}
// Check for unlikely conditions on the mask, such as no initiators assigned.
if (em.getKnownInitiatorNetworkIds() == null || em.getKnownInitiatorNetworkIds().isEmpty()) {
_logger.error("UnManagedExportMask with ID: " + maskIdStr + " does not contain any RP initiators. Ignoring for ingestion.");
continue;
}
boolean foundMask = false;
for (String wwn : em.getKnownInitiatorNetworkIds()) {
for (Entry<String, AbstractChangeTrackingSet<String>> siteInitEntry : protectionSystem.getSiteInitiators().entrySet()) {
if (siteInitEntry.getValue().contains(wwn)) {
_logger.info(String.format("UnManagedVolume %s was found in UnManagedExportMask %s and will be ingested (if not ingested already)", unManagedVolume.getLabel(), em.getMaskName()));
unManagedRPExportMasks.add(em);
foundMask = true;
break;
}
}
if (foundMask) {
break;
}
}
}
return unManagedRPExportMasks;
}
use of com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask in project coprhd-controller by CoprHD.
the class IngestExportStrategy method ingestExportMasks.
/**
* After volume object gets created successfully locally, now start
* running ingest associated masks of the volume
*/
public <T extends BlockObject> T ingestExportMasks(UnManagedVolume unManagedVolume, T blockObject, IngestionRequestContext requestContext) throws IngestionException {
_logger.info("ingesting export masks for requestContext " + requestContext.getCurrentUnmanagedVolume());
if (null != requestContext.getExportGroup()) {
if (null != unManagedVolume.getUnmanagedExportMasks() && !unManagedVolume.getUnmanagedExportMasks().isEmpty()) {
List<URI> unManagedMaskUris = new ArrayList<URI>(Collections2.transform(unManagedVolume.getUnmanagedExportMasks(), CommonTransformerFunctions.FCTN_STRING_TO_URI));
List<UnManagedExportMask> unManagedMasks = _dbClient.queryObject(UnManagedExportMask.class, unManagedMaskUris);
int originalSize = unManagedMasks.size();
MutableInt masksIngestedCount = new MutableInt(0);
// Ingest Associated Masks
ingestExportOrchestrator.ingestExportMasks(requestContext, unManagedVolume, blockObject, unManagedMasks, masksIngestedCount);
_logger.info("{} of {} unmanaged export masks were ingested", masksIngestedCount, originalSize);
List<String> errorMessages = requestContext.getErrorMessagesForVolume(unManagedVolume.getNativeGuid());
// If the internal flags are set, return the block object
if (blockObject.checkInternalFlags(Flag.PARTIALLY_INGESTED)) {
_logger.info("block object {} is partially ingested", blockObject.forDisplay());
// check if none of the export masks are ingested
if (masksIngestedCount.intValue() == 0) {
if (null != errorMessages && !errorMessages.isEmpty()) {
throw IngestionException.exceptions.unmanagedVolumeMasksNotIngestedAdditionalInfo(unManagedVolume.getLabel(), Joiner.on(", ").join(errorMessages));
} else {
throw IngestionException.exceptions.unmanagedVolumeMasksNotIngested(unManagedVolume.getLabel());
}
} else {
// If the unmanaged volume is not marked for deletion, then it should be updated with the changes done.
requestContext.addDataObjectToUpdate(unManagedVolume, unManagedVolume);
_logger.info("all export masks of unmanaged volume {} have been ingested, " + "but the volume is still marked as partially ingested, returning block object {}", unManagedVolume.forDisplay(), blockObject.forDisplay());
return blockObject;
}
}
if (unManagedVolume.getUnmanagedExportMasks().size() != originalSize) {
// delete this volume only if the masks are ingested.
if (VolumeIngestionUtil.canDeleteUnManagedVolume(unManagedVolume)) {
_logger.info("Marking UnManaged Volume {} inactive as it doesn't have any associated unmanaged export masks ", unManagedVolume.getNativeGuid());
boolean isRPVolume = VolumeIngestionUtil.checkUnManagedResourceIsRecoverPointEnabled(unManagedVolume);
// if its RP volume and non RP exported, then check whether the RP CG is fully ingested
if (isRPVolume && VolumeIngestionUtil.checkUnManagedResourceIsNonRPExported(unManagedVolume)) {
_logger.info("unmanaged volume {} is both RecoverPoint protected and exported to another Host or Cluster", unManagedVolume.forDisplay());
Set<DataObject> updateObjects = requestContext.getDataObjectsToBeUpdatedMap().get(unManagedVolume.getNativeGuid());
if (updateObjects == null) {
updateObjects = new HashSet<DataObject>();
requestContext.getDataObjectsToBeUpdatedMap().put(unManagedVolume.getNativeGuid(), updateObjects);
}
List<UnManagedVolume> ingestedUnManagedVolumes = requestContext.findAllUnManagedVolumesToBeDeleted();
ingestedUnManagedVolumes.add(unManagedVolume);
UnManagedProtectionSet umpset = VolumeIngestionUtil.getUnManagedProtectionSetForUnManagedVolume(requestContext, unManagedVolume, _dbClient);
// unmanaged volume has already been ingested. In this case, try to get it from the managed volume
if (umpset == null) {
umpset = VolumeIngestionUtil.getUnManagedProtectionSetForManagedVolume(requestContext, blockObject, _dbClient);
}
// If fully ingested, then setup the RP CG too.
if (VolumeIngestionUtil.validateAllVolumesInCGIngested(ingestedUnManagedVolumes, umpset, requestContext, _dbClient)) {
VolumeIngestionUtil.validateRPVolumesAlignWithIngestVpool(requestContext, umpset, _dbClient);
VolumeIngestionUtil.setupRPCG(requestContext, umpset, unManagedVolume, updateObjects, _dbClient);
} else {
// else mark the volume as internal. This will be marked visible when the RP CG is ingested
blockObject.addInternalFlags(BlockRecoverPointIngestOrchestrator.INTERNAL_VOLUME_FLAGS);
}
}
unManagedVolume.setInactive(true);
requestContext.getUnManagedVolumesToBeDeleted().add(unManagedVolume);
} else {
// If the unmanaged volume is not marked for deletion, then it should be updated with the changes done.
requestContext.addDataObjectToUpdate(unManagedVolume, unManagedVolume);
}
return blockObject;
} else {
if (null != errorMessages && !errorMessages.isEmpty()) {
Collections.sort(errorMessages);
throw IngestionException.exceptions.unmanagedVolumeMasksNotIngestedAdditionalInfo(unManagedVolume.getLabel(), "\n\n" + Joiner.on("\n\n").join(errorMessages));
} else {
throw IngestionException.exceptions.unmanagedVolumeMasksNotIngested(unManagedVolume.getLabel());
}
}
}
}
return blockObject;
}
use of com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedExportMask in project coprhd-controller by CoprHD.
the class MaskPerHostIngestOrchestrator method getExportMaskAlreadyIngested.
/**
* maskPerHost Mode guaranteed to have initiators in only 1 export mask
* always.
*/
@Override
protected ExportMask getExportMaskAlreadyIngested(UnManagedExportMask mask, DbClient dbClient) {
ExportMask eMask = null;
boolean maskFound = false;
List<URI> initiatorUris = new ArrayList<URI>(Collections2.transform(mask.getKnownInitiatorUris(), CommonTransformerFunctions.FCTN_STRING_TO_URI));
for (URI ini : initiatorUris) {
List<URI> exportMaskUris = _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getExportMaskInitiatorConstraint(ini.toString()));
if (null == exportMaskUris) {
return eMask;
}
for (URI eMaskUri : exportMaskUris) {
ExportMask potentialMask = _dbClient.queryObject(ExportMask.class, eMaskUri);
if (potentialMask.getStorageDevice() != null && potentialMask.getStorageDevice().equals(mask.getStorageSystemUri())) {
_logger.info("Found Mask {} with matching initiator and matching Storage System", eMaskUri);
eMask = potentialMask;
maskFound = true;
break;
} else {
_logger.info("Found Mask {} with matching initiator and unmatched Storage System. Skipping mask", eMaskUri);
}
}
if (maskFound) {
break;
}
}
return eMask;
}
Aggregations