/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.client.upgrade.callbacks; import com.emc.storageos.db.client.constraint.AlternateIdConstraint; import com.emc.storageos.db.client.constraint.URIQueryResultList; import com.emc.storageos.db.client.model.DiscoveredDataObject; import com.emc.storageos.db.client.model.HostInterface; import com.emc.storageos.db.client.model.StoragePool; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.model.VirtualPool; import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback; import com.emc.storageos.svcs.errorhandling.resources.MigrationCallbackException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class ScaleIOPoolAndStorageSystemMigration extends BaseCustomMigrationCallback { private static final Logger log = LoggerFactory.getLogger(ScaleIOPoolAndStorageSystemMigration.class); private static final Map<URI, StorageSystem> SIO_STORAGE_SYSTEMS = new HashMap<>(); private static final List<String> STORAGE_SYSTEM_PROPERTIES = Arrays.asList("systemType", "label", "nativeGuid", "inactive"); @Override public void process() throws MigrationCallbackException { log.info("Migrating any ScaleIO StoragePools"); // First determine if there are any SIO based StorageSystems if (!haveAnySIOStorageSystems()) { log.info("There are no ScaleIO StorageSystems, skipping ScaleIOPoolAndStorageSystemMigration."); return; } log.info("Number ScaleIO StorageSystems found: {}", SIO_STORAGE_SYSTEMS.size()); Map<URI, StoragePool> sioStoragePools = getSIOStoragePools(); Set<URI> storageSystemURIs = new HashSet<>(); for (StoragePool pool : sioStoragePools.values()) { StorageSystem associatedStorage = SIO_STORAGE_SYSTEMS.get(pool.getStorageDevice()); if (associatedStorage != null) { log.info(String.format("StoragePool %s will be migrated", pool.getNativeGuid())); pool.setNativeGuid(pool.getNativeId()); pool.setSupportedResourceTypes(StoragePool.SupportedResourceTypes.THICK_ONLY.name()); pool.setMaximumThickVolumeSize(1048576L); pool.setMinimumThickVolumeSize(1L); pool.setMaximumThinVolumeSize(0L); pool.setMinimumThinVolumeSize(0L); dbClient.persistObject(pool); // Migrate the associated StorageSystem only once if (!storageSystemURIs.contains(associatedStorage.getId())) { log.info(String.format("StorageSystem %s will be migrated", associatedStorage.getNativeGuid())); associatedStorage.setLabel(associatedStorage.getNativeGuid()); dbClient.persistObject(associatedStorage); storageSystemURIs.add(associatedStorage.getId()); } } } List<URI> virtualPoolURIs = dbClient.queryByType(VirtualPool.class, true); Iterator<VirtualPool> virtualPoolIterator = dbClient.queryIterativeObjects(VirtualPool.class, virtualPoolURIs); while (virtualPoolIterator.hasNext()) { VirtualPool virtualPool = virtualPoolIterator.next(); StringSet protocols = virtualPool.getProtocols(); if (protocols != null && protocols.contains(HostInterface.Protocol.ScaleIO.name())) { log.info(String.format("VirtualPool %s will be migrated", virtualPool.getLabel())); virtualPool.setSupportedProvisioningType(VirtualPool.ProvisioningType.Thick.name()); dbClient.persistObject(virtualPool); } } } /** * Examine SIO_STORAGE_SYSTEM and return a mapping of StoragePool URI to StoragePool objects * * @return Map or StoragePool URI to StoragePool Object */ Map<URI, StoragePool> getSIOStoragePools() { Map<URI, StoragePool> storagePoolMap = new HashMap<>(); // Iterate through each SIO StorageSystem found and run constraint query to // look up the list of associated StoragePools for (StorageSystem storageSystem : SIO_STORAGE_SYSTEMS.values()) { List<StoragePool> storagePools = getStoragePoolsForStorageSystem(storageSystem); for (StoragePool storagePool : storagePools) { if (!storagePoolMap.containsKey(storagePool.getId())) { storagePoolMap.put(storagePool.getId(), storagePool); } } } return storagePoolMap; } /** * Query StoragePools associated to the StorageSystem * * @param storageSystem [in] - StorageSystem object * @return List of StoragePools associated with the StorageSystem * */ private List<StoragePool> getStoragePoolsForStorageSystem(StorageSystem storageSystem) { URIQueryResultList storagePoolURIs = new URIQueryResultList(); AlternateIdConstraint storagePoolByStorageDevice = AlternateIdConstraint.Factory. getConstraint(StoragePool.class, "storageDevice", storageSystem.getId().toString()); dbClient.queryByConstraint(storagePoolByStorageDevice, storagePoolURIs); List<StoragePool> storagePools = new ArrayList<>(); Iterator<URI> storagePoolIter = storagePoolURIs.iterator(); while (storagePoolIter.hasNext()) { URI storagePoolURI = storagePoolIter.next(); StoragePool storagePool = dbClient.queryObject(StoragePool.class, storagePoolURI); if (storagePool != null && !storagePool.getInactive()) { storagePools.add(storagePool); } } return storagePools; } /** * Check if there are any ScaleIO StorageSystems in the DB. * * @return true IFF there are 1 or more StorageSystems with systemType = scaleio. The SIO_STORAGE_SYSTEMS * map will be populate with a mapping of the SIO StorageSystem URIs to StorageSystem object. Note, that * the StorageSystems will have limited properties based on the query to populate them. * */ private boolean haveAnySIOStorageSystems() { List<URI> allStorageSystems = dbClient.queryByType(StorageSystem.class, true); Iterator<StorageSystem> storageSystemIterator = dbClient.queryIterativeObjectFields(StorageSystem.class, STORAGE_SYSTEM_PROPERTIES, allStorageSystems); while (storageSystemIterator.hasNext()) { StorageSystem storageSystem = storageSystemIterator.next(); if (storageSystem.getSystemType().equals(DiscoveredDataObject.Type.scaleio.name())) { SIO_STORAGE_SYSTEMS.put(storageSystem.getId(), storageSystem); } } return !SIO_STORAGE_SYSTEMS.isEmpty(); } }