/*
* Copyright (c) 2016 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.upgrade.callbacks;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.BlockMirror;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.DiscoveredDataObject;
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;
import com.emc.storageos.svcs.errorhandling.resources.MigrationCallbackException;
/**
* If we are upgrading from any version 3.5 or before, the BlockObject.systemType
* property should be set to according to the system type of the BlockObject's
* storage device. This includes Volumes, BlockSnapshots, and BlockMirrors.
*
* @author beachn
* @since 3.5+
*/
public class BlockObjectSystemTypeMigration extends BaseCustomMigrationCallback {
private static final Logger logger = LoggerFactory.getLogger(BlockObjectSystemTypeMigration.class);
@Override
public void process() throws MigrationCallbackException {
DbClient dbClient = getDbClient();
Map<URI, String> storageSystemTypeMap = new HashMap<URI, String>();
int pageSize = 100;
int totalBlockObjectCount = 0;
int blockObjectUpdatedCount = 0;
List<Class<? extends BlockObject>> classesToProcess = new ArrayList<Class<? extends BlockObject>>();
classesToProcess.add(Volume.class);
classesToProcess.add(BlockSnapshot.class);
classesToProcess.add(BlockMirror.class);
for (Class<? extends BlockObject> clazz : classesToProcess) {
URI nextId = null;
while (true) {
List<URI> blockObjectUris = dbClient.queryByType(clazz, true, nextId, pageSize);
if (blockObjectUris == null || blockObjectUris.isEmpty()) {
break;
}
logger.info("processing page of {} {} BlockObjects", blockObjectUris.size(), clazz.getSimpleName());
Iterator<? extends BlockObject> pageIterator = dbClient.queryIterativeObjects(clazz, blockObjectUris, true);
while (pageIterator.hasNext()) {
BlockObject blockObject = pageIterator.next();
if (blockObject != null && NullColumnValueGetter.isNullValue(blockObject.getSystemType())) {
logger.info("starting migration of BlockObject " + blockObject.forDisplay());
String deviceSystemType = getDeviceSystemType(dbClient, storageSystemTypeMap, blockObject);
if (deviceSystemType != null) {
blockObject.setSystemType(deviceSystemType);
dbClient.updateObject(blockObject);
blockObjectUpdatedCount++;
logger.info("set storage system type to {} for BlockObject {}",
deviceSystemType, blockObject.forDisplay());
} else {
logger.warn("could not determine storage system type for BlockObject {}",
blockObject.forDisplay());
}
}
}
nextId = blockObjectUris.get(blockObjectUris.size() - 1);
totalBlockObjectCount += blockObjectUris.size();
}
}
logger.info("Updated storage system type on {} of {} BlockObjects in the system",
blockObjectUpdatedCount, totalBlockObjectCount);
}
/**
* Get a storage device system type from the database or from the cache.
*
* @param dbClient the database client
* @param storageSystemTypeMap a map of storage system URIs to system types
* @param blockObject the block object to check system type for
* @return the storage device system type
*/
private String getDeviceSystemType(DbClient dbClient, Map<URI, String> storageSystemTypeMap, BlockObject blockObject) {
String deviceSystemType = null;
URI storageSystemUri = blockObject.getStorageController();
if (NullColumnValueGetter.isNullURI(storageSystemUri)) {
logger.warn("storage controller URI for BlockObject {} was null", blockObject.forDisplay());
} else if (storageSystemTypeMap.containsKey(storageSystemUri)) {
deviceSystemType = storageSystemTypeMap.get(storageSystemUri);
} else {
StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, storageSystemUri);
if (storageSystem != null) {
deviceSystemType = storageSystem.checkIfVmax3() ? DiscoveredDataObject.Type.vmax3.name() : storageSystem.getSystemType();
storageSystemTypeMap.put(storageSystemUri, deviceSystemType);
logger.info("adding storage system type {} for storage system URI {}",
deviceSystemType, storageSystemUri);
} else {
logger.warn("could not find storage system by URI {} for BlockObject {}",
storageSystemUri, blockObject.forDisplay());
}
}
return deviceSystemType;
}
}