/* * Copyright (c) 2008-2011 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.fast; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.URIUtil; import com.emc.storageos.db.client.constraint.AlternateIdConstraint; import com.emc.storageos.db.client.constraint.URIQueryResultList; import com.emc.storageos.db.client.model.StoragePool; import com.emc.storageos.db.client.model.StorageTier; import com.emc.storageos.plugins.BaseCollectionException; import com.emc.storageos.plugins.common.Constants; import com.emc.storageos.plugins.common.Processor; import com.emc.storageos.volumecontroller.impl.ControllerUtils; import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator; import com.emc.storageos.volumecontroller.impl.utils.ImplicitPoolMatcher; import com.google.common.base.Splitter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * All FAST related Processors extends this Class * Reusable code across FAST Processors have been placed here. */ public abstract class AbstractFASTPolicyProcessor extends Processor { private final static Logger _logger = LoggerFactory.getLogger(AbstractFASTPolicyProcessor.class); /** * Check if Storage Tier exists in DB. * * @param tierNativeGuid * @param _dbClient * @return StorageTier * @throws IOException */ protected StorageTier checkStorageTierExistsInDB(String tierNativeGuid, DbClient _dbClient) throws IOException { StorageTier tier = null; // use NativeGuid to lookup Tiers in DB @SuppressWarnings("deprecation") List<URI> storageTierUris = _dbClient.queryByConstraint(AlternateIdConstraint.Factory .getStorageTierByIdConstraint(tierNativeGuid)); if (!storageTierUris.isEmpty()) { tier = _dbClient.queryObject(StorageTier.class, storageTierUris.get(0)); } return tier; } /** * get nativeGuid for vmax Tiers * * @param tierID * @return */ protected String getTierNativeGuidForVnx(String tierID) { Iterable<String> tierIDItr = Splitter.on(Constants.PATH_DELIMITER_PATTERN).limit(4) .split(tierID); String poolID = getValueAtGivenPositionFromTierId(tierIDItr, 3); String storageSystemId = getValueAtGivenPositionFromTierId(tierIDItr, 0) + Constants.PLUS + getValueAtGivenPositionFromTierId(tierIDItr, 1); String tierName = getValueAtGivenPositionFromTierId(tierIDItr, 2); return NativeGUIDGenerator.generateStorageTierNativeGuidForVnxTier(storageSystemId, poolID, tierName); } /** * get nativeGuid for vnx Tiers * * @param tierID * @return */ protected String getTierNativeGuidForVMax(String tierID) { Iterable<String> tierIDItr = Splitter.on(Constants.PATH_DELIMITER_PATTERN).limit(3) .split(tierID); String storageSystemId = getValueAtGivenPositionFromTierId(tierIDItr, 0) + Constants.PLUS + getValueAtGivenPositionFromTierId(tierIDItr, 1); String tierName = getValueAtGivenPositionFromTierId(tierIDItr, 2); return NativeGUIDGenerator.generateStorageTierNativeGuidForVmaxTier(storageSystemId, tierName); } protected String getTierNativeGuidFromTierInstance(CIMInstance tierInstance) { String tierID = tierInstance.getObjectPath().getKey(Constants.INSTANCEID) .getValue().toString(); String tierNativeGuid = null; if (tierID.toLowerCase().contains(Constants.SYMMETRIX)) { tierNativeGuid = getTierNativeGuidForVMax(tierID); } else { tierNativeGuid = getTierNativeGuidForVnx(tierID); } return tierNativeGuid; } /** * Get FAST Policy Name * PolicyRuleName doesn't need to be same across multiple Arrays. * * @param policyObjectPath * @return String format of: Array Serial ID + FASTPOLICY + policyRuleName */ protected String getFASTPolicyID(CIMObjectPath policyObjectPath) { String array = policyObjectPath.getKey(Constants.SYSTEMNAME).getValue() .toString(); String policyRuleName = policyObjectPath.getKey(Constants.POLICYRULENAME) .getValue().toString(); return getFASTPolicyID(array, policyRuleName); } /** * Get FAST Policy Name * PolicyRuleName doesn't need to be same across multiple Arrays. * * @param systemName - system name from CIMObjectPath in format of: Array Serial ID * @param policyRuleName - auto tier policy name, e.g., LOW * @return String format of: Array Serial ID + FASTPOLICY + policyRuleName */ protected String getFASTPolicyID(String systemName, String policyRuleName) { try { return NativeGUIDGenerator.generateAutoTierPolicyNativeGuid(systemName, policyRuleName, NativeGUIDGenerator.FASTPOLICY); } catch (Exception e) { _logger.error("FAST Policy Id creation failed", e); } return null; } /** * Get FAST Policy Name from DeviceGroup CIMObjectPath * * @param deviceGroupPath * @return FASTPolicyName */ protected String getFASTPolicyNameFromDeviceGroupID(CIMObjectPath deviceGroupPath) { String groupID = deviceGroupPath.getKey(Constants.INSTANCEID).getValue() .toString(); // always bourne created Group will have fixed format SerialID+FASTPolicyName_DeviceGroup String bourneCreatedDeviceGroupName = groupID.split(Constants.PATH_DELIMITER_REGEX)[2]; String fastPolicyName = bourneCreatedDeviceGroupName.substring(0, bourneCreatedDeviceGroupName.lastIndexOf(Constants.HYPHEN)); return fastPolicyName; } /** * get Device GroupName * * @param deviceGroupPath * @return bourneCreatedDeviceGroupName */ protected String getDeviceGroupName(CIMObjectPath deviceGroupPath) { String groupID = deviceGroupPath.getKey(Constants.INSTANCEID).getValue() .toString(); // always bourne created Group will have fixed format // SerialID+FASTPolicyName_DeviceGroup String bourneCreatedDeviceGroupName = groupID.split(Constants.PATH_DELIMITER_REGEX)[2]; return bourneCreatedDeviceGroupName; } /** * add DeviceGroup Path to Map, and generate sDeviceGroup--->FASTPolicy Mapping * * @param keyMap * @param deviceGroupPath * @param resultKey * @throws BaseCollectionException */ protected void addDeviceGroupPathToMap( Map<String, Object> keyMap, CIMObjectPath deviceGroupPath, String resultKey) throws BaseCollectionException { addPath(keyMap, resultKey, deviceGroupPath); // generate DeviceGroup--->FASTPolicy Mapping String fastPolicy = getFASTPolicyNameFromDeviceGroupID(deviceGroupPath); keyMap.put(deviceGroupPath.getKey(Constants.INSTANCEID).getValue().toString(), (CIMObjectPath) keyMap.get(fastPolicy)); } /** * Get storage Pool from DB * TODO move DB related methods to DBUtil * * @param poolObjectPath * @param dbClient * @return */ protected URI getStoragePoolURI(CIMObjectPath poolObjectPath, DbClient dbClient) { URI poolURI = null; try { String poolNativeGuid = NativeGUIDGenerator .generateNativeGuidForPool(poolObjectPath); URIQueryResultList result = new URIQueryResultList(); dbClient.queryByConstraint(AlternateIdConstraint.Factory .getStoragePoolByNativeGuidConstraint(poolNativeGuid), result); while (result.iterator().hasNext()) { poolURI = result.iterator().next(); } } catch (Exception e) { _logger.error("Extracting StoragePool URi for PoolID {} failed -->", poolObjectPath, e); } return poolURI; } /** * add StoragePools to FAST Policy Object * Existing Pools associated with Policy will get replaced. * * @param policyObjectPath * @param it * @param dbClient * @throws IOException */ @SuppressWarnings("unchecked") protected void addStoragePoolstoPolicy(List<CIMObjectPath> policyObjectPaths, Iterator<CIMObjectPath> it, DbClient dbClient, Map<String, Object> keyMap, String tierID) throws IOException { // PolicyToPoolInfo ---> Map <PolicyName, Set<String> Pools> // set already at runtime Map<String, Set<String>> policytopoolMapping = (Map<String, Set<String>>) keyMap .get(Constants.POLICY_TO_POOLS_MAPPING); while (it.hasNext()) { CIMObjectPath poolObjectPath = it.next(); URI poolURI = getStoragePoolURI(poolObjectPath, dbClient); if (null != poolURI) { for (CIMObjectPath policyObjectPath : policyObjectPaths) { String policyID = getFASTPolicyID(policyObjectPath); if (!policytopoolMapping.containsKey(policyID)) { policytopoolMapping.put(policyID, new HashSet<String>()); } policytopoolMapping.get(policyID).add(poolURI.toString()); } } } } /** * create Storage Tier * * @param tierInstance * @param tierObject * @param tierNativeGuid * @param vmaxFastPolicyUri * @param tierList * @return */ protected StorageTier createStorageTier( CIMInstance tierInstance, StorageTier tierObject, String tierNativeGuid, URI vmaxFastPolicyUri, List<StorageTier> newTierList, List<StorageTier> updateTierList, String driveTechnology) { boolean isNewTier = false; if (null == tierObject) { tierObject = new StorageTier(); tierObject.setId(URIUtil.createId(StorageTier.class)); tierObject.setNativeGuid(tierNativeGuid); isNewTier = true; } tierObject.setPercentage(getCIMPropertyValue(tierInstance, Constants.PERCENTAGE)); tierObject.setLabel(getCIMPropertyValue(tierInstance, Constants.ELEMENTNAME)); tierObject.setDiskDriveTechnology(driveTechnology); String totalCapacity = getCIMPropertyValue(tierInstance, Constants.TOTAL_CAPACITY); tierObject.setTotalCapacity(ControllerUtils.convertBytesToKBytes(totalCapacity)); if (isNewTier) { newTierList.add(tierObject); } else { updateTierList.add(tierObject); } return tierObject; } /** * Create Storage Tiers for VNX, if not present already * Add Tier Uris to Storage Pool Object for both vmax and vnx * * @param storagePoolpath * @param it * @param dbClient * @param keyMap * @throws IOException */ protected void addTiersToPool( CIMObjectPath storagePoolpath, Iterator<CIMInstance> it, DbClient dbClient, Map<String, Object> keyMap) throws IOException { Map<URI, StoragePool> poolsToMatchWithVpool = (Map<URI, StoragePool>) keyMap .get(Constants.MODIFIED_STORAGEPOOLS); Map<String, String> tierUtilizationPercentageMap = new HashMap<String, String>(); CIMInstance tierInstance = null; List<StorageTier> _tierList = new ArrayList<StorageTier>(); Set<String> tierUris = new HashSet<String>(); while (it.hasNext()) { try { tierInstance = it.next(); String tierUtilizationPercentage = tierInstance.getPropertyValue( Constants.PERCENTAGE).toString(); String driveTechnologyIdentifier = tierInstance.getPropertyValue( Constants.TECHNOLOGY).toString(); String driveTechnology = StorageTier.SupportedTiers .getTier(driveTechnologyIdentifier); if (null == driveTechnology) { _logger.info("Unsupported Drive Type :" + driveTechnologyIdentifier); } else { tierUtilizationPercentageMap.put(driveTechnology, tierUtilizationPercentage); } String tierNativeGuid = getTierNativeGuidFromTierInstance(tierInstance); StorageTier tierObject = checkStorageTierExistsInDB(tierNativeGuid, dbClient); if (null == tierObject) { tierObject = createStorageTier(tierInstance, tierObject, tierNativeGuid, null, _tierList, null, driveTechnology); dbClient.createObject(tierObject); } tierUris.add(tierObject.getId().toString()); } catch (Exception e) { _logger.error("Determing Drive Type, Tier Info failed for {} : ", tierInstance.getObjectPath(), e); } } URI poolURI = getStoragePoolURI(storagePoolpath, dbClient); StoragePool pool = dbClient.queryObject(StoragePool.class, poolURI); if (null != pool) { pool.addTierUtilizationPercentage(tierUtilizationPercentageMap); // add to modified pool list if pool's property which is required for vPool matcher, has changed. // If the modified list already has this pool, skip the check. if (!poolsToMatchWithVpool.containsKey(pool.getId()) && ImplicitPoolMatcher.checkPoolPropertiesChanged(pool.getTiers(), tierUris)) { poolsToMatchWithVpool.put(pool.getId(), pool); } pool.addTiers(tierUris); dbClient.persistObject(pool); } } }