use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class RPHelper method rollbackProtectionOnVolume.
/**
* Rollback protection specific fields on the existing volume. This is normally invoked if there are
* errors during a change vpool operation. We want to return the volume back to its un-protected state
* or in the case of upgrade to MP then to remove any MP features from the protected volume.
*
* One of the biggest motivations is to ensure that the old vpool is set back on the existing volume.
*
* @param volume Volume to remove protection from
* @param oldVpool The old vpool, this the original vpool of the volume before trying to add protection
* @param dbClient DBClient object
*/
public static void rollbackProtectionOnVolume(Volume volume, VirtualPool oldVpool, DbClient dbClient) {
// Rollback any RP specific changes to this volume
if (volume.checkForRp()) {
if (!VirtualPool.vPoolSpecifiesProtection(oldVpool)) {
_log.info(String.format("Start rollback of RP protection changes for volume [%s] (%s)...", volume.getLabel(), volume.getId()));
// List of volume IDs to clean up from the ProtectionSet
List<String> protectionSetVolumeIdsToRemove = new ArrayList<String>();
protectionSetVolumeIdsToRemove.add(volume.getId().toString());
// All source volumes in this CG
List<Volume> cgSourceVolumes = getCgSourceVolumes(volume.getConsistencyGroup(), dbClient);
// Only rollback the Journals if there is only one volume in the CG and it's the one we're
// trying to roll back.
boolean lastSourceVolumeInCG = (cgSourceVolumes != null && cgSourceVolumes.size() == 1 && cgSourceVolumes.get(0).getId().equals(volume.getId()));
// order can be placed immediately.
if (lastSourceVolumeInCG) {
List<Volume> journals = getCgVolumes(dbClient, volume.getConsistencyGroup(), Volume.PersonalityTypes.METADATA.name());
for (Volume journal : journals) {
_log.info(String.format("Rolling back RP Journal (%s)", journal.getLabel()));
protectionSetVolumeIdsToRemove.add(journal.getId().toString());
rollbackVolume(journal.getId(), dbClient);
}
}
// Null out any RP specific fields on the volume
volume.setConsistencyGroup(NullColumnValueGetter.getNullURI());
volume.setPersonality(NullColumnValueGetter.getNullStr());
volume.setProtectionController(NullColumnValueGetter.getNullURI());
volume.setRSetName(NullColumnValueGetter.getNullStr());
volume.setInternalSiteName(NullColumnValueGetter.getNullStr());
volume.setRpCopyName(NullColumnValueGetter.getNullStr());
StringSet resetRpTargets = volume.getRpTargets();
if (resetRpTargets != null) {
// Rollback any target volumes that were created
for (String rpTargetId : resetRpTargets) {
protectionSetVolumeIdsToRemove.add(rpTargetId);
rollbackVolume(URI.create(rpTargetId), dbClient);
}
resetRpTargets.clear();
volume.setRpTargets(resetRpTargets);
}
// Clean up the Protection Set
if (!NullColumnValueGetter.isNullNamedURI(volume.getProtectionSet())) {
ProtectionSet protectionSet = dbClient.queryObject(ProtectionSet.class, volume.getProtectionSet());
if (protectionSet != null) {
// Remove volume IDs from the Protection Set
protectionSet.getVolumes().removeAll(protectionSetVolumeIdsToRemove);
_log.info(String.format("Removing the following volumes from Protection Set [%s] (%s): %s", protectionSet.getLabel(), protectionSet.getId(), Joiner.on(',').join(protectionSetVolumeIdsToRemove)));
// inactive.
if (lastSourceVolumeInCG) {
_log.info(String.format("Setting Protection Set [%s] (%s) to inactive", protectionSet.getLabel(), protectionSet.getId()));
protectionSet.setInactive(true);
}
dbClient.updateObject(protectionSet);
}
}
volume.setProtectionSet(NullColumnValueGetter.getNullNamedURI());
} else {
_log.info(String.format("Rollback changes for existing protected RP volume [%s]...", volume.getLabel()));
// No specific rollback steps for existing protected volumes
}
// the backing volumes if they were set to the new vpool.
if (RPHelper.isVPlexVolume(volume, dbClient)) {
if (null == volume.getAssociatedVolumes()) {
// this is a rollback situation, so we probably don't want to
// throw another exception...
_log.warn("VPLEX volume {} has no backend volumes.", volume.forDisplay());
} else {
for (String associatedVolId : volume.getAssociatedVolumes()) {
Volume associatedVolume = dbClient.queryObject(Volume.class, URI.create(associatedVolId));
if (associatedVolume != null && !associatedVolume.getInactive()) {
if (!NullColumnValueGetter.isNullURI(associatedVolume.getVirtualPool()) && associatedVolume.getVirtualPool().equals(volume.getVirtualPool())) {
associatedVolume.setVirtualPool(oldVpool.getId());
_log.info(String.format("Backing volume [%s] has had its virtual pool rolled back to [%s].", associatedVolume.getLabel(), oldVpool.getLabel()));
}
associatedVolume.setConsistencyGroup(NullColumnValueGetter.getNullURI());
dbClient.updateObject(associatedVolume);
}
// before we get here anyway.
if (!oldVpool.getMultivolumeConsistency()) {
associatedVolume.setConsistencyGroup(NullColumnValueGetter.getNullURI());
}
dbClient.updateObject(associatedVolume);
}
}
}
// Set the old vpool back on the volume
_log.info(String.format("Resetting vpool on volume [%s](%s) from (%s) back to its original vpool (%s)", volume.getLabel(), volume.getId(), volume.getVirtualPool(), oldVpool.getId()));
volume.setVirtualPool(oldVpool.getId());
dbClient.updateObject(volume);
_log.info(String.format("Rollback of RP protection changes for volume [%s] (%s) has completed.", volume.getLabel(), volume.getId()));
}
}
use of com.emc.storageos.db.client.model.ProtectionSet in project coprhd-controller by CoprHD.
the class RPHelper method getVolumesToDelete.
/**
* This method will return all volumes that should be deleted based on the entire list of volumes to be deleted.
* If this is the last source volume in the CG, this method will return all journal volumes as well.
*
* @param reqDeleteVolumes all volumes in the delete request
* @param dbClient DbClient
* @return list of volumes to unexport and delete
* @throws InternalException
* @throws URISyntaxException
*/
public static Set<URI> getVolumesToDelete(Collection<URI> reqDeleteVolumes, DbClient dbClient) throws InternalException {
_log.info(String.format("Getting all RP volumes to delete for requested list: %s", reqDeleteVolumes));
Set<URI> volumeIDs = new HashSet<URI>();
Set<URI> protectionSetIds = new HashSet<URI>();
Iterator<Volume> volumes = dbClient.queryIterativeObjects(Volume.class, reqDeleteVolumes, true);
// Divide the RP volumes by BlockConsistencyGroup so we can determine if all volumes in the
// RP consistency group are being removed.
Map<URI, Set<URI>> cgsToVolumesForDelete = new HashMap<URI, Set<URI>>();
// to that volume to the list of volumes to be deleted
while (volumes.hasNext()) {
Volume volume = volumes.next();
// get the list of all source and target volumes in the same replication set as the
// volume passed in
List<Volume> allVolsInRSet = getVolumesInRSet(volume, dbClient);
List<URI> allVolsInRSetURI = new ArrayList<URI>();
URI cgURI = null;
// 3. If partially ingested volume, clean up corresponding unmanaged protection set
for (Volume vol : allVolsInRSet) {
allVolsInRSetURI.add(vol.getId());
if (!NullColumnValueGetter.isNullURI(vol.getConsistencyGroup())) {
cgURI = vol.getConsistencyGroup();
}
if (!NullColumnValueGetter.isNullNamedURI(vol.getProtectionSet())) {
// Keep track of the protection sets for a cleanup operation later in case we
// find any stale volume references
protectionSetIds.add(vol.getProtectionSet().getURI());
}
// If this is a partially ingested RP volume, clean up the corresponding unmanaged protection set
List<UnManagedProtectionSet> umpsets = CustomQueryUtility.getUnManagedProtectionSetByManagedVolumeId(dbClient, vol.getId().toString());
for (UnManagedProtectionSet umpset : umpsets) {
umpset.getManagedVolumeIds().remove(vol.getId().toString());
// Clean up the volume's reference, if any, in the unmanaged volumes associated with the unmanaged protection set
for (String umv : umpset.getUnManagedVolumeIds()) {
UnManagedVolume umVolume = dbClient.queryObject(UnManagedVolume.class, URI.create(umv));
StringSet rpManagedSourceVolumeInfo = umVolume.getVolumeInformation().get(SupportedVolumeInformation.RP_MANAGED_SOURCE_VOLUME.toString());
StringSet rpManagedTargetVolumeInfo = umVolume.getVolumeInformation().get(SupportedVolumeInformation.RP_MANAGED_TARGET_VOLUMES.toString());
if (rpManagedSourceVolumeInfo != null && !rpManagedSourceVolumeInfo.isEmpty()) {
rpManagedSourceVolumeInfo.remove(vol.getId().toString());
}
if (rpManagedTargetVolumeInfo != null && !rpManagedTargetVolumeInfo.isEmpty()) {
rpManagedTargetVolumeInfo.remove(vol.getId().toString());
}
dbClient.updateObject(umVolume);
}
dbClient.updateObject(umpset);
}
}
// Add the replication set volume IDs to the list of volumes to be deleted
_log.info(String.format("Adding volume %s to the list of volumes to be deleted", allVolsInRSetURI.toString()));
volumeIDs.addAll(allVolsInRSetURI);
// the entire CG which would indicate journals are also being deleted.
if (cgURI != null) {
if (cgsToVolumesForDelete.get(cgURI) == null) {
cgsToVolumesForDelete.put(cgURI, new HashSet<URI>());
}
cgsToVolumesForDelete.get(cgURI).addAll(allVolsInRSetURI);
} else {
_log.warn(String.format("Unable to find a valid CG for replication set volumes %s. Unable to determine if the entire CG is being deleted as part of this request.", allVolsInRSetURI.toString()));
}
}
// Determine if we're deleting all of the volumes in this consistency group
for (Map.Entry<URI, Set<URI>> cgToVolumesForDelete : cgsToVolumesForDelete.entrySet()) {
BlockConsistencyGroup cg = null;
URI cgURI = cgToVolumesForDelete.getKey();
cg = dbClient.queryObject(BlockConsistencyGroup.class, cgURI);
List<Volume> cgVolumes = getAllCgVolumes(cgURI, dbClient);
// determine if all of the source and target volumes in the consistency group are on the list
// of volumes to delete; if so, we will add the journal volumes to the list.
// also create a list of stale volumes to be removed from the protection set
boolean wholeCG = true;
if (cgVolumes != null) {
for (Volume cgVol : cgVolumes) {
Set<URI> cgVolsToDelete = cgToVolumesForDelete.getValue();
// determine if it's a journal or another source/target not being deleted.
if (!cgVolsToDelete.contains(cgVol.getId())) {
// Do not consider VPlex backing volumes or inactive volumes
if (!cgVol.getInactive() && NullColumnValueGetter.isNotNullValue(cgVol.getPersonality())) {
if (!Volume.PersonalityTypes.METADATA.toString().equals(cgVol.getPersonality())) {
// the volume is either a source or target; this means there are other volumes in the rset
wholeCG = false;
break;
}
}
}
}
}
if (wholeCG) {
// add them to the list of volumes to be removed
if (cg != null) {
List<Volume> allJournals = getCgVolumes(dbClient, cg.getId(), Volume.PersonalityTypes.METADATA.toString());
if (allJournals != null && !allJournals.isEmpty()) {
Set<URI> allJournalURIs = new HashSet<URI>();
for (Volume journalVolume : allJournals) {
allJournalURIs.add(journalVolume.getId());
}
_log.info(String.format("Determined that this is a request to delete consistency group %s. Adding journal volumes to the list of volumes to delete: %s", cgURI, allJournalURIs.toString()));
volumeIDs.addAll(allJournalURIs);
}
} else {
_log.info(String.format("Could not determine journal volumes for consistency group %s .", cgToVolumesForDelete.getKey()));
}
} else {
_log.info(String.format("Consistency group %s will not be removed. Only a subset of the replication sets are being removed.", cgToVolumesForDelete.getKey()));
}
}
// "bad things" from happening.
for (URI protSetId : protectionSetIds) {
List<String> staleVolumes = new ArrayList<String>();
ProtectionSet protectionSet = dbClient.queryObject(ProtectionSet.class, protSetId);
if (protectionSet.getVolumes() != null) {
for (String protSetVol : protectionSet.getVolumes()) {
URI protSetVolUri = URI.create(protSetVol);
if (!volumeIDs.contains(protSetVolUri)) {
Volume vol = dbClient.queryObject(Volume.class, protSetVolUri);
if (vol == null || vol.getInactive()) {
// The ProtectionSet references a stale volume that no longer exists in the DB.
_log.info("ProtectionSet " + protectionSet.getLabel() + " references volume " + protSetVol + " that no longer exists in the DB. Removing this volume reference.");
staleVolumes.add(protSetVol);
}
}
}
}
// remove stale entries from protection set
if (!staleVolumes.isEmpty()) {
for (String vol : staleVolumes) {
protectionSet.getVolumes().remove(vol);
}
dbClient.updateObject(protectionSet);
}
}
return volumeIDs;
}
Aggregations