/** * Link the target volumes to the passed in source volume * * @param unManagedProtectionSet unmanaged protection set * @param sourceVolume RP CG source volume * @param rset RP CG replication set * @param rpWwnToNativeWwn Map of RP volume WWN to native volume WWN - required for XIO but * harmless otherwise * @param storageNativeIdPrefixes List of XIO systems discovered in ViPR * @param dbClient DB client instance * @return rpTargetVolumeIds Set of unmanaged target volume ids for the given source volume */ private StringSet linkTargetVolumes( UnManagedProtectionSet unManagedProtectionSet, UnManagedVolume sourceVolume, GetRSetResponse rset, Map<String, String> rpWwnToNativeWwn, List<String> storageNativeIdPrefixes, DbClient dbClient) { StringSet rpTargetVolumeIds = new StringSet(); // Find the target volumes associated with this source volume. for (GetVolumeResponse targetVolume : rset.getVolumes()) { // Find this volume in UnManagedVolumes based on wwn UnManagedVolume targetUnManagedVolume = null; String targetWwn = rpWwnToNativeWwn.get(targetVolume.getWwn()); if (targetWwn != null) { targetUnManagedVolume = findUnManagedVolumeForWwn(targetWwn, dbClient, storageNativeIdPrefixes); } if (null == targetUnManagedVolume) { log.info( "Protection Set {} contains unknown target volume: {}. Skipping.", unManagedProtectionSet.getNativeGuid(), targetVolume.getWwn()); continue; } // Don't bother if we just re-found the source device if (targetUnManagedVolume.getId().equals(sourceVolume.getId())) { continue; } // Check if this volume is already managed, which would indicate it has already been partially // ingested Volume targetManagedVolume = DiscoveryUtils.checkManagedVolumeExistsInDBByWwn(dbClient, targetVolume.getWwn()); if (null != targetManagedVolume) { log.info( "Protection Set {} has an orphaned unmanaged target volume {}. Skipping.", unManagedProtectionSet.getNativeGuid(), targetUnManagedVolume.getLabel()); continue; } log.info("\tfound target volume {}", targetUnManagedVolume.forDisplay()); // Add the source unmanaged volume ID to the target volume StringSet rpUnManagedSourceVolumeId = new StringSet(); rpUnManagedSourceVolumeId.add(sourceVolume.getId().toString()); targetUnManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_UNMANAGED_SOURCE_VOLUME.toString(), rpUnManagedSourceVolumeId); // Update the target unmanaged volume with the source managed volume ID unManagedVolumesToUpdateByWwn.put(targetUnManagedVolume.getWwn(), targetUnManagedVolume); // Store the unmanaged target ID in the source volume rpTargetVolumeIds.add(targetUnManagedVolume.getId().toString()); } return rpTargetVolumeIds; }
/** * Update the common fields in the UnManagedVolume to reflect RP characteristics Is this volume * SOURCE, TARGET, or JOURNAL? What's the RP Copy Name of this volume? (what copy does it belong * to?) * * @param unManagedProtectionSet * @param unManagedVolume * @param personalityType * @param volume * @param dbClient */ private void updateCommonRPProperties( UnManagedProtectionSet unManagedProtectionSet, UnManagedVolume unManagedVolume, String personalityType, GetVolumeResponse volume, DbClient dbClient) { StringSet rpCopyName = new StringSet(); rpCopyName.add(volume.getRpCopyName()); StringSet rpInternalSiteName = new StringSet(); rpInternalSiteName.add(volume.getInternalSiteName()); if (volume.isProductionStandby()) { unManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_STANDBY_COPY_NAME.toString(), rpCopyName); unManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_STANDBY_INTERNAL_SITENAME.toString(), rpInternalSiteName); // If this volume is flagged as production standby it indicates that this RP CG is // MetroPoint. Set the IS_MP flag on UnManagedProtectionSet to TRUE. This only needs // to be done once. String metroPoint = unManagedProtectionSet .getCGCharacteristics() .get(UnManagedProtectionSet.SupportedCGCharacteristics.IS_MP.name()); if (metroPoint == null || metroPoint.isEmpty() || !Boolean.parseBoolean(metroPoint)) { // Set the flag to true if it hasn't already been set unManagedProtectionSet .getCGCharacteristics() .put( UnManagedProtectionSet.SupportedCGCharacteristics.IS_MP.name(), Boolean.TRUE.toString()); } } else { unManagedVolume.putVolumeInfo(SupportedVolumeInformation.RP_COPY_NAME.toString(), rpCopyName); unManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_INTERNAL_SITENAME.toString(), rpInternalSiteName); } StringSet personality = new StringSet(); personality.add(personalityType); unManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_PERSONALITY.toString(), personality); StringSet rpProtectionSystemId = new StringSet(); rpProtectionSystemId.add(unManagedProtectionSet.getProtectionSystemUri().toString()); unManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_PROTECTIONSYSTEM.toString(), rpProtectionSystemId); // Filter in RP source vpools, filter out everything else (if source) // Filter out certain vpools if target/journal filterProtectedVpools(dbClient, unManagedVolume, personality.iterator().next()); }
/** * Update (if it exists) the journal UnManagedVolume objects with RP information needed for * ingestion * * @param unManagedProtectionSet unmanaged protection set * @param cg CG response got back from RP system * @param rpCopyAccessStateMap Map to hold the access state of the replication sets. * @param rpWwnToNativeWwn Map of RP volume WWN to native volume WWN - required for XIO but * harmless otherwise * @param storageNativeIdPrefixes List of XIO systems discovered in ViPR * @param dbClient DB client instance */ private void mapCgJournals( UnManagedProtectionSet unManagedProtectionSet, GetCGsResponse cg, Map<String, String> rpCopyAccessStateMap, Map<String, String> rpWwnToNativeWwn, List<String> storageNativeIdPrefixes, DbClient dbClient) { for (GetCopyResponse copy : cg.getCopies()) { String accessState = copy.getAccessState(); for (GetVolumeResponse volume : copy.getJournals()) { // Find this volume in UnManagedVolumes based on wwn UnManagedVolume unManagedVolume = findUnManagedVolumeForWwn(volume.getWwn(), dbClient, storageNativeIdPrefixes); // Check if this volume is already managed, which would indicate it has already been // partially ingested Volume managedVolume = DiscoveryUtils.checkManagedVolumeExistsInDBByWwn(dbClient, volume.getWwn()); // Add the WWN to the unmanaged protection set, regardless of whether this volume is // unmanaged or not. unManagedProtectionSet.getVolumeWwns().add(volume.getWwn()); if (null == unManagedVolume && null == managedVolume) { log.info( "Protection Set {} contains unknown Journal volume: {}. Skipping.", unManagedProtectionSet.getNativeGuid(), volume.getWwn()); continue; } if (null != managedVolume) { log.info( "Protection Set {} contains volume {} that is already managed", unManagedProtectionSet.getNativeGuid(), volume.getWwn()); // make sure it's in the UnManagedProtectionSet's ManagedVolume ids if (!unManagedProtectionSet .getManagedVolumeIds() .contains(managedVolume.getId().toString())) { unManagedProtectionSet.getManagedVolumeIds().add(managedVolume.getId().toString()); } if (null != unManagedVolume) { log.info( "Protection Set {} also has an orphaned UnManagedVolume {} that will be removed", unManagedProtectionSet.getNativeGuid(), unManagedVolume.getLabel()); // remove the unManagedVolume from the UnManagedProtectionSet's UnManagedVolume ids unManagedProtectionSet .getUnManagedVolumeIds() .remove(unManagedVolume.getId().toString()); unManagedVolumesToDelete.add(unManagedVolume); } // because this volume is already managed, we can just continue to the next continue; } // at this point, we have an legitimate UnManagedVolume whose RP properties should be // updated log.info("Processing Journal UnManagedVolume {}", unManagedVolume.forDisplay()); // Capture the access state rpCopyAccessStateMap.put(volume.getRpCopyName(), accessState); // Add the unmanaged volume to the list (if it's not there already) if (!unManagedProtectionSet .getUnManagedVolumeIds() .contains(unManagedVolume.getId().toString())) { unManagedProtectionSet.getUnManagedVolumeIds().add(unManagedVolume.getId().toString()); } updateCommonRPProperties( unManagedProtectionSet, unManagedVolume, Volume.PersonalityTypes.METADATA.name(), volume, dbClient); rpWwnToNativeWwn.put(volume.getWwn(), unManagedVolume.getWwn()); unManagedVolumesToUpdateByWwn.put(unManagedVolume.getWwn(), unManagedVolume); } } }
/** * Update (if it exists) the source and target UnManagedVolume objects with RP information needed * for ingestion * * @param unManagedProtectionSet unmanaged protection set * @param cg CG response got back from RP system * @param rpCopyAccessStateMap Map to hold the access state of the replication sets * @param rpWwnToNativeWwn Map of RP volume WWN to native volume WWN - required for XIO but * harmless otherwise * @param storageNativeIdPrefixes List of XIO systems discovered in ViPR * @param dbClient DB client instance */ private void mapCgSourceAndTargets( UnManagedProtectionSet unManagedProtectionSet, GetCGsResponse cg, Map<String, String> rpCopyAccessStateMap, Map<String, String> rpWwnToNativeWwn, List<String> storageNativeIdPrefixes, DbClient dbClient) { for (GetRSetResponse rset : cg.getRsets()) { for (GetVolumeResponse volume : rset.getVolumes()) { // Find this volume in UnManagedVolumes based on wwn UnManagedVolume unManagedVolume = findUnManagedVolumeForWwn(volume.getWwn(), dbClient, storageNativeIdPrefixes); // Check if this volume is already managed, which would indicate it has already been // partially ingested Volume managedVolume = DiscoveryUtils.checkManagedVolumeExistsInDBByWwn(dbClient, volume.getWwn()); // Add the WWN to the unmanaged protection set, regardless of whether this volume is // unmanaged or not. unManagedProtectionSet.getVolumeWwns().add(volume.getWwn()); if (null == unManagedVolume && null == managedVolume) { log.info( "Protection Set {} contains unknown Replication Set volume: {}. Skipping.", unManagedProtectionSet.getNativeGuid(), volume.getWwn()); continue; } if (null != managedVolume) { log.info( "Protection Set {} contains volume {} that is already managed", unManagedProtectionSet.getNativeGuid(), volume.getWwn()); // make sure it's in the UnManagedProtectionSet's ManagedVolume ids if (!unManagedProtectionSet .getManagedVolumeIds() .contains(managedVolume.getId().toString())) { unManagedProtectionSet.getManagedVolumeIds().add(managedVolume.getId().toString()); } if (!managedVolume.checkInternalFlags(Flag.INTERNAL_OBJECT) && null != unManagedVolume) { log.info( "Protection Set {} also has an orphaned UnManagedVolume {} that will be removed", unManagedProtectionSet.getNativeGuid(), unManagedVolume.getLabel()); // remove the unManagedVolume from the UnManagedProtectionSet's UnManagedVolume ids unManagedProtectionSet .getUnManagedVolumeIds() .remove(unManagedVolume.getId().toString()); unManagedVolumesToDelete.add(unManagedVolume); // because this volume is already managed, we can just continue to the next continue; } } // at this point, we have an legitimate UnManagedVolume whose RP properties should be // updated log.info("Processing Replication Set UnManagedVolume {}", unManagedVolume.forDisplay()); // Add the unmanaged volume to the list (if it's not there already) if (!unManagedProtectionSet .getUnManagedVolumeIds() .contains(unManagedVolume.getId().toString())) { unManagedProtectionSet.getUnManagedVolumeIds().add(unManagedVolume.getId().toString()); } // Update the fields in the UnManagedVolume to reflect RP characteristics String personality = Volume.PersonalityTypes.SOURCE.name(); if (!volume.isProduction()) { personality = Volume.PersonalityTypes.TARGET.name(); } updateCommonRPProperties( unManagedProtectionSet, unManagedVolume, personality, volume, dbClient); // Update other RP properties for source/targets // What Replication Set does this volume belong to? (so we can associate sources to // targets.) // What is the access state. StringSet rpAccessState = new StringSet(); rpAccessState.add(rpCopyAccessStateMap.get(volume.getRpCopyName())); unManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_ACCESS_STATE.toString(), rpAccessState); StringSet rsetName = new StringSet(); rsetName.add(rset.getName()); unManagedVolume.putVolumeInfo(SupportedVolumeInformation.RP_RSET_NAME.toString(), rsetName); rpWwnToNativeWwn.put(volume.getWwn(), unManagedVolume.getWwn()); unManagedVolumesToUpdateByWwn.put(unManagedVolume.getWwn(), unManagedVolume); } // Now that we've processed all of the sources and targets, we can mark all of the target // devices in the source devices. for (GetVolumeResponse volume : rset.getVolumes()) { // Only process source volumes here. if (!volume.isProduction()) { continue; } // Find this volume in UnManagedVolumes based on wwn // See if the unmanaged volume is in the list of volumes to update // (it should be, unless the backing array has not been discovered) UnManagedVolume unManagedVolume = null; String wwn = rpWwnToNativeWwn.get(volume.getWwn()); if (wwn != null) { unManagedVolume = findUnManagedVolumeForWwn(wwn, dbClient, storageNativeIdPrefixes); } if (null == unManagedVolume) { log.info( "Protection Set {} contains unknown volume: {}. Skipping.", unManagedProtectionSet.getNativeGuid(), volume.getWwn()); continue; } log.info("Linking target volumes to source volume {}", unManagedVolume.forDisplay()); StringSet rpTargetVolumeIds = linkTargetVolumes( unManagedProtectionSet, unManagedVolume, rset, rpWwnToNativeWwn, storageNativeIdPrefixes, dbClient); // Add the unmanaged target IDs to the source unmanaged volume unManagedVolume.putVolumeInfo( SupportedVolumeInformation.RP_UNMANAGED_TARGET_VOLUMES.toString(), rpTargetVolumeIds); unManagedVolumesToUpdateByWwn.put(unManagedVolume.getWwn(), unManagedVolume); } } }