/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.client.upgrade.callbacks; import java.net.URI; import java.util.Iterator; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.constraint.AlternateIdConstraint; import com.emc.storageos.db.client.constraint.URIQueryResultList; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback; /** * Migration process sets the relationship between VPLEX volume full copies and * their source VPLEX volume. */ public class VplexVolumeFullCopyMigration extends BaseCustomMigrationCallback { private static final Logger s_logger = LoggerFactory.getLogger(VplexVolumeFullCopyMigration.class); @Override public void process() { s_logger.info("Excecuting VPLEX full copy migration"); DbClient dbClient = getDbClient(); try { List<URI> volumeUris = dbClient.queryByType(Volume.class, true); Iterator<Volume> volumes = dbClient.queryIterativeObjects(Volume.class, volumeUris, true); while (volumes.hasNext()) { StringSet vplexFullCopyVolumeIds = new StringSet(); Volume volume = volumes.next(); StringSet associatedVolumeIds = volume.getAssociatedVolumes(); // VPLEX volumes, except those ingested but not migrated, have associated volumes. // Those that are ingested and have not been migrated will not have full copies // so we don;t need to worry about those. if ((associatedVolumeIds != null) && (!associatedVolumeIds.isEmpty())) { s_logger.info("Checking VPLEX volume {}", volume.getLabel()); for (String associatedVolumeId : associatedVolumeIds) { URI associatedVolumeURI = URI.create(associatedVolumeId); Volume associatedVolume = dbClient.queryObject(Volume.class, associatedVolumeURI); // Log an error and continue if there is no such volume. if (associatedVolume == null) { s_logger.info("Associated volume {} for volume {} not found.", associatedVolumeURI, volume.getId()); continue; } // We want the "source" associated volume. This is the backend volume // in the same varray as the VPLEX volume. This is the volume used // when full copies of the VPLEX volume are created. Since we do a // native full copy of this backend volume, the full copy relationships // are established for the native copy. We can use this information // to set the relationships for the VPLEX volume itself. if (!associatedVolume.getVirtualArray().equals(volume.getVirtualArray())) { continue; } s_logger.info("Found source side backend volume {}", associatedVolume.getLabel()); // See if the backend volume has any full copies. StringSet fullCopyVolumeIds = associatedVolume.getFullCopies(); if (fullCopyVolumeIds == null || fullCopyVolumeIds.isEmpty()) { continue; } s_logger.info("Source side backend volume has {} full copies", fullCopyVolumeIds.size()); // If so, then this VPLEX volume is a source for one or // more VPLEX fully copy volumes. for (String fullCopyVolumeId : fullCopyVolumeIds) { // For each full copy of the backend volume, determine the // VPLEX volume using that copy. Those VPLEX volumes are // full copies of the VPLEX volume currently being processed. URIQueryResultList queryResults = new URIQueryResultList(); dbClient.queryByConstraint( AlternateIdConstraint.Factory.getVolumeByAssociatedVolumesConstraint(fullCopyVolumeId), queryResults); Iterator<URI> queryResultsIter = queryResults.iterator(); while (queryResultsIter.hasNext()) { // Set the source for this VPLEX full copy volume // to the VPLEX volume being processed and persist. Volume vplexFullCopyVolume = dbClient.queryObject(Volume.class, queryResultsIter.next()); s_logger.info("Found VPLEX volume {} for backend full copy", vplexFullCopyVolume.getLabel()); vplexFullCopyVolume.setAssociatedSourceVolume(volume.getId()); dbClient.persistObject(vplexFullCopyVolume); s_logger.info("Set full copy source"); // Also add this VPLEX full volume copy to the full copies list // for the source volume. vplexFullCopyVolumeIds.add(vplexFullCopyVolume.getId().toString()); } } } } // Now if we did find full copies for the volume being processed // set them and persist. if (!vplexFullCopyVolumeIds.isEmpty()) { volume.setFullCopies(vplexFullCopyVolumeIds); dbClient.persistObject(volume); s_logger.info("Set {} full copies for VPLEX volume {}", vplexFullCopyVolumeIds.size(), volume.getLabel()); } } } catch (Exception ex) { s_logger.error("Exception occured while migrating VPLEX volume full copy relationshsips."); s_logger.error(ex.getMessage(), ex); } } }