/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.utils.attrmatchers; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; import com.emc.storageos.db.client.model.StoragePool; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.model.VirtualPool; import com.emc.storageos.volumecontroller.AttributeMatcher; import com.google.common.base.Joiner; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; /* * In case of VMAX, if drive Type is not selected then always prefer FC Pool for provisioning. * If FC Pool not available, then preferred order "FC","SAS","NL_SAS","SATA","SSD" */ public class PoolPreferenceBasedOnDriveMathcer extends AttributeMatcher { private static final Logger _logger = LoggerFactory.getLogger(PoolPreferenceBasedOnDriveMathcer.class); private static final String[] driveTypeOrder = { "FC", "SAS", "NL_SAS", "SATA", "SSD" }; @Override protected boolean isAttributeOn(Map<String, Object> attributeMap) { // ignore preference in case of array affinity if (attributeMap != null && attributeMap.containsKey(Attributes.array_affinity.name())) { Boolean arrayAffinity = (Boolean) attributeMap.get(Attributes.array_affinity.name()); if (arrayAffinity) { return false; } } // run only if System Type is VMAX. return (null != attributeMap && attributeMap.containsKey(Attributes.system_type.toString()) && ((StringSet) attributeMap.get(Attributes.system_type.toString())) .contains(VirtualPool.SystemType.vmax.toString())); } @Override protected List<StoragePool> matchStoragePoolsWithAttributeOn(List<StoragePool> allPools, Map<String, Object> attributeMap, StringBuffer errorMessage) { List<StoragePool> optimalPools = new ArrayList<StoragePool>(); ListMultimap<String, StoragePool> groupSPByDriveType = ArrayListMultimap.create(); _logger.info("Optimal Pool Selection Matcher Started {} :", Joiner.on("\t").join(getNativeGuidFromPools(allPools))); for (StoragePool pool : allPools) { if (null != pool.getSupportedDriveTypes()) { for (String driveTypes : pool.getSupportedDriveTypes()) { String[] driveTypeArr = driveTypes.split(","); for (String driveType : driveTypeArr) { groupSPByDriveType.put(driveType, pool); } } } } _logger.info("Grouping Storage Pools by Drive Types : {}", Joiner.on("\t").join(groupSPByDriveType.asMap().entrySet())); for (String driveType : driveTypeOrder) { _logger.info("Processing Pools with Drive Type {}", driveType); Collection<StoragePool> pools = groupSPByDriveType.asMap().get(driveType); if (null != pools && !pools.isEmpty()) { optimalPools.addAll(pools); break; } else { _logger.info("Not able to find any Pools with Drive Type {}", driveType); } } // CTRL-12532: For storage pools of type FTS, drive type will have "Unknown" value. // if the optimal pools is empty, it means that all pools are have a drive type other than FC, SAS, NL_SAS, SATA, SSD. // In this case, return all the pools. if (optimalPools.isEmpty()) { _logger.info("Storage pool list is empty after filtering based on optimal pools. Returning back the full list."); optimalPools = allPools; } if (CollectionUtils.isEmpty(optimalPools)) { errorMessage.append("No matching pools available for pool preference based on the drive type. "); _logger.error(errorMessage.toString()); } _logger.info("Optimal Pool Selection Matcher Ended {} :", Joiner.on("\t").join(getNativeGuidFromPools(optimalPools))); return optimalPools; } }