/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.client.upgrade.callbacks; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; 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.BlockObject; import com.emc.storageos.db.client.model.DiscoveredDataObject; import com.emc.storageos.db.client.model.ExportMask; import com.emc.storageos.db.client.model.Initiator; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.StringMap; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback; import com.emc.storageos.db.client.util.StringSetUtil; import com.emc.storageos.db.client.util.WWNUtility; import com.emc.storageos.svcs.errorhandling.resources.MigrationCallbackException; /** * Migration process to handle setting of _userAddedVolumes _userAddedInitiators and _initiators * in the VPlex ExportMasks * * @author tahals * @since 2.0 */ public class VplexExportMaskInitiatorsAndVolumesMigration extends BaseCustomMigrationCallback { private static final Logger log = LoggerFactory.getLogger(VplexExportMaskInitiatorsAndVolumesMigration.class); @Override public void process() throws MigrationCallbackException { DbClient dbClient = getDbClient(); try { List<URI> exportMaskUris = dbClient.queryByType(ExportMask.class, true); Iterator<ExportMask> exportMasks = dbClient.queryIterativeObjects(ExportMask.class, exportMaskUris, true); while (exportMasks.hasNext()) { ExportMask exportMask = exportMasks.next(); try { URI storageSytsemURI = exportMask.getStorageDevice(); StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, storageSytsemURI); // We only need to update VPlex ExportMask if ((storageSystem != null) && (DiscoveredDataObject.Type.vplex.name().equals(storageSystem .getSystemType()))) { // Volumes list can be inconsistent only when its created by ViPR if (exportMask.getCreatedBySystem()) { log.info("Looking at export mask " + exportMask.getMaskName() + " Export Mask ID is :" + exportMask.getId() + "created by system is " + exportMask.getCreatedBySystem()); StringMap volumeMaps = exportMask.getVolumes(); if (volumeMaps != null && !volumeMaps.isEmpty()) { Set<String> volumeIds = volumeMaps.keySet(); List<BlockObject> volumes = new ArrayList<BlockObject>(); for (String volumeId : volumeIds) { BlockObject bo = BlockObject.fetch(dbClient, URI.create(volumeId)); if (bo != null) { if (bo.getWWN() == null) { log.info("Skipping volume " + bo.getId() + " " + bo.getLabel() + " as its wwn is null."); ; } else { volumes.add(bo); } } } StringMap userAddedVolumesMap = exportMask.getUserAddedVolumes(); if (userAddedVolumesMap == null && !volumes.isEmpty()) { // If there is nothing in the userAddedVolumesMap then add all the // volumes from the EXportMask Volumes list log.info("Adding volumes to the userCreatedVolumes " + volumes + "to the export mask " + exportMask.getMaskName() + " export mask ID is :" + exportMask.getId()); try { exportMask.addToUserCreatedVolumes(volumes); } catch (Exception volEx) { log.error("Exception occured while adding volumes to the userCreatedVolumes"); log.error(volEx.getMessage(), volEx); } } else { // Iterate through all the volumes and add those volumes which are not in the // user added list for (BlockObject volume : volumes) { if (volume.getWWN() != null && !volume.getWWN().isEmpty()) { if (userAddedVolumesMap.get(BlockObject.normalizeWWN(volume.getWWN())) == null) { log.info("Adding volume to the userCreatedVolumes " + volume + "to the export mask " + exportMask.getMaskName() + "exportmask ID is :" + exportMask.getId()); try { exportMask.addToUserCreatedVolumes(volume); } catch (Exception volEx) { log.error("Exception occured while adding volume to the userCreatedVolumes"); log.error(volEx.getMessage(), volEx); } } } } } // Add all the initiators from the initiators list if any to the userAddedInitiators populateExportMaskUserAddedInitiators(exportMask); dbClient.persistObject(exportMask); } } else { log.info("Looking at export mask " + exportMask.getMaskName() + " Export Mask ID is :" + exportMask.getId() + "created by system is " + exportMask.getCreatedBySystem()); // First add all the initiators from the initiators list if any to the userAddedInitiators populateExportMaskUserAddedInitiators(exportMask); // initiators list can be inconsistent when we are reusing existing // storage view in which case createdBySystem will be false // Add existing initiators to the initiators list if we can find Initiator object for those pwwn if (exportMask.getExistingInitiators() != null && !exportMask.getExistingInitiators().isEmpty()) { StringSet existingInitiators = exportMask.getExistingInitiators(); List<URI> existingInitiatorsURIs = new ArrayList<URI>(); for (String pwwn : existingInitiators) { Initiator initiator = findInitiatorInDB(pwwn); if (initiator != null) { existingInitiatorsURIs.add(initiator.getId()); } } if (exportMask.getInitiators() == null && !existingInitiatorsURIs.isEmpty()) { log.info("Adding existingInitiators to the initiators " + existingInitiatorsURIs + "to the export mask " + exportMask.getMaskName() + "export mask ID is :" + exportMask.getId()); exportMask.setInitiators(StringSetUtil.uriListToStringSet(existingInitiatorsURIs)); } else { for (URI uri : existingInitiatorsURIs) { log.info("Adding existingInitiator to the initiators " + uri + "to the export mask " + exportMask.getMaskName() + "export mask ID is :" + exportMask.getId()); exportMask.getInitiators().add(uri.toString()); } } } dbClient.persistObject(exportMask); } } } catch (Exception emex) { log.error("Exception occured while migrating VPLEX ExportMask " + exportMask.getId() + " " + exportMask.getMaskName()); log.error(emex.getMessage(), emex); } } } catch (Exception ex) { log.error("Exception occured while migrating VPLEX ExportMask "); log.error(ex.getMessage(), ex); } log.info("Done VplexExportMaskInitiatorsAndVolumesMigration."); } /** * This method returns initiator if it exist in database * * @param pwwn Initiators pwwn * @return initiator object or null * @throws IOException */ private Initiator findInitiatorInDB(String pwwn) throws IOException { Initiator initiator = null; String portWWN = WWNUtility.getWWNWithColons(pwwn); log.info("Looking for initiator {} in database", portWWN); URIQueryResultList queryResults = new URIQueryResultList(); dbClient.queryByConstraint(AlternateIdConstraint.Factory .getInitiatorPortInitiatorConstraint(portWWN), queryResults); Iterator<URI> resultsIter = queryResults.iterator(); if (resultsIter.hasNext()) { log.info("Found initiator {}", portWWN); initiator = dbClient.queryObject(Initiator.class, resultsIter.next()); } return initiator; } /** * This method adds initiators if any to the userAddedInitiators in the * mentioned exportMask. * * @param exportMask The exportMask * @return returns same exportMask by making changes if applicable */ private ExportMask populateExportMaskUserAddedInitiators(ExportMask exportMask) { if (exportMask.getInitiators() != null && !exportMask.getInitiators().isEmpty()) { StringMap userAddedInitiatorsMap = exportMask.getUserAddedInitiators(); List<Initiator> initiators = new ArrayList<Initiator>(); for (String initiatorId : exportMask.getInitiators()) { Initiator initiator = dbClient.queryObject(Initiator.class, URI.create(initiatorId)); if (initiator != null) { initiators.add(initiator); } } // If there is nothing in the userAddedInitiatorsMap then add all the // initiators from the ExportMask initiators list to the user added initiators if (userAddedInitiatorsMap == null && !initiators.isEmpty()) { exportMask.addToUserCreatedInitiators(initiators); log.info("Adding initiators to the userCreatedInitiators " + initiators + "to the export mask " + exportMask.getMaskName() + "export mask ID is :" + exportMask.getId()); } else { // Iterate through all the initiators and add those initiators // which are not in the user added list for (Initiator initiator : initiators) { if (userAddedInitiatorsMap.get(Initiator.normalizePort(initiator.getInitiatorPort())) == null) { log.info("Adding initiator to the userCreatedInitiators" + initiator + "to the export mask " + exportMask.getMaskName() + "exportmask ID is :" + exportMask.getId()); exportMask.addToUserCreatedInitiators(initiator); } } } } return exportMask; } }