/* * Copyright (c) 2016 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.model.BlockConsistencyGroup; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback; import com.emc.storageos.db.client.util.NullColumnValueGetter; /** * Migration handler to upgrade the SRDF volumes field replicationGroupInstance * * This migration handler does the same as VolumesInCGMigration except for SRDF volumes * which were skipped in that migration handler * * It fixes an issue with SRDF volumes where the replicationGroupInstance field was not * populated and caused issues with delete * * It will be checked into the ViPR 3.0 patch 1 branch but will not be run as part of the * upgrade to ViPR 3.0 or 3.0p1. * * It will go in the ViPR 3.1 migration handler area so that it can be run as part * of the upgrade to 3.1 and beyond. * * This migration callbacks will also be available to be run manually from a new feature * in dbutils which allows customers to run specified migration callbacks at any time. Customers * who have SRDF volumes and upgraded from ViPR 2.4.1 to ViPR 3.0 should run the new tool as * follows: * * "/opt/storageos/bin/dbutils run_migration_callback com.emc.storageos.db.client.upgrade.callbacks.SRDFVolumesInCGMigration" * */ public class SRDFVolumesInCGMigration extends BaseCustomMigrationCallback { private static final Logger log = LoggerFactory.getLogger(SRDFVolumesInCGMigration.class); @Override public void process() { updateVolumesInConsistencyGroup(); } /** * Migrate the SRDF volumes in CG */ private void updateVolumesInConsistencyGroup() { log.info("Migrating SRDF volumes in CG" ); DbClient dbClient = getDbClient(); List<URI> volumeURIs = dbClient.queryByType(Volume.class, true); Iterator<Volume> volumes = dbClient.queryIterativeObjects(Volume.class, volumeURIs); int totalVolumes = 0; int volumesUpdated = 0; while (volumes.hasNext()) { totalVolumes++; Volume volume = volumes.next(); if (!NullColumnValueGetter.isNullURI(volume.getStorageController()) && !NullColumnValueGetter.isNullURI(volume.getConsistencyGroup())) { URI cgUri = volume.getConsistencyGroup(); URI storageUri = volume.getStorageController(); BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, cgUri); StorageSystem system = dbClient.queryObject(StorageSystem.class, storageUri); if (cg == null || system == null) { log.warn(String.format("Volume %s is being skipped because the refrenced CG or storage system is null; cgUri: %s; storageUri: %s", volume.getId().toString(), cgUri.toString(), storageUri.toString())); continue; } if (volume.getSrdfParent() != null || volume.getSrdfTargets() != null) { String replicationGroupName = cg.getCgNameOnStorageSystem(volume.getStorageController()); if (replicationGroupName != null && !replicationGroupName.isEmpty() && NullColumnValueGetter.isNullValue(volume.getReplicationGroupInstance())) { log.info("updating the SRDF volume {} replicationgroup {}", volume.getLabel(), replicationGroupName); volume.setReplicationGroupInstance(replicationGroupName); dbClient.updateObject(volume); volumesUpdated++; } } } } log.info(String.format("%d volumes updated out of a total of %d volumes", volumesUpdated, totalVolumes)); } }