/* * Copyright (c) 2008-2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import javax.cim.CIMProperty; import javax.wbem.CloseableIterator; import javax.wbem.client.WBEMClient; import com.emc.storageos.volumecontroller.impl.plugins.SMICommunicationInterface; import com.google.common.base.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.plugins.AccessProfile; import com.emc.storageos.plugins.BaseCollectionException; import com.emc.storageos.plugins.common.Constants; import com.emc.storageos.plugins.common.domainmodel.Operation; import com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.detailedDiscovery.VolHostIOObject; import com.emc.storageos.volumecontroller.impl.smis.SmisCommandHelper; import com.emc.storageos.volumecontroller.impl.smis.SmisConstants; import com.emc.storageos.volumecontroller.impl.smis.SmisUtils; public class LunMaskingProcessor extends StorageProcessor { private static final String STORAGE_VOLUME_PREFIX = "storagevolume"; private Logger _logger = LoggerFactory.getLogger(LunMaskingProcessor.class); private List<Object> _args; private DbClient _dbClient; @Override public void processResult( Operation operation, Object resultObj, Map<String, Object> keyMap) throws BaseCollectionException { @SuppressWarnings("unchecked") final Iterator<CIMObjectPath> it = (Iterator<CIMObjectPath>) resultObj; Map<String, VolHostIOObject> volToIolimits = new HashMap<String, VolHostIOObject>(); List<CIMObjectPath> processedSGCoPs = new ArrayList<CIMObjectPath>(); Map<String, String> volToFastPolicy = new HashMap<String, String>(); WBEMClient client = SMICommunicationInterface.getCIMClient(keyMap); CIMObjectPath maskingViewPath = getObjectPathfromCIMArgument(_args); _dbClient = (DbClient) keyMap.get(Constants.dbClient); AccessProfile profile = (AccessProfile) keyMap.get(Constants.ACCESSPROFILE); URI systemId = profile.getSystemId(); try { StorageSystem device = _dbClient.queryObject(StorageSystem.class, systemId); while (it.hasNext()) { CIMObjectPath path = it.next(); // if cascaded SG, note down the Host Io limits, and get the // child SGs Host Io limits and volumes. // If io limit is not set on child SG, then use the parent, else // use io limit on child always if (path.toString().contains(SmisCommandHelper.MASKING_GROUP_TYPE.SE_DeviceMaskingGroup.name())) { List<CIMObjectPath> paths = getChildGroupsifCascaded(path, client); if (!paths.isEmpty()) { _logger.info("Cascaded SG Detected"); CIMInstance csgInstance = client.getInstance(path, false, true, SmisConstants.PS_HOST_IO); String parentHostIoBw = String.valueOf(csgInstance.getPropertyValue(SmisConstants.EMC_MAX_BANDWIDTH)); String parentHostIoPs = String.valueOf(csgInstance.getPropertyValue(SmisConstants.EMC_MAX_IO)); for (CIMObjectPath childPath : paths) { addIoLimitsOnVolume(client, childPath, volToIolimits, volToFastPolicy, parentHostIoBw, parentHostIoPs); } processedSGCoPs.addAll(paths); } else { _logger.info("Non cascaded SG Detected"); addIoLimitsOnVolume(client, path, volToIolimits, volToFastPolicy, "0", "0"); processedSGCoPs.add(path); } } // Clar_LunMaskingSCSIProtocolController-->StorageVolume, if volume entry is there, // then consider those as exported Volumes. String systemName = (String) maskingViewPath.getKey(Constants.SYSTEMNAME).getValue(); if (systemName.toLowerCase().contains(Constants.CLARIION) && path.toString().toLowerCase().contains(STORAGE_VOLUME_PREFIX)) { String volumeNativeGuid = getVolumeNativeGuid(path); VolHostIOObject obj = new VolHostIOObject(); obj.setVolNativeGuid(volumeNativeGuid); obj.setHostIoBw("0"); obj.setHostIops("0"); volToIolimits.put(volumeNativeGuid, obj); } } // Store all the exported Volumes of all Protocol Controllers // During creation of UnManaged Volume in // StorageVolumeInfoProcesssor, this collection // will be used to filter out already exported Volumes if (!keyMap.containsKey(Constants.EXPORTED_VOLUMES)) { keyMap.put(Constants.EXPORTED_VOLUMES, volToIolimits); } else { @SuppressWarnings("unchecked") Map<String, VolHostIOObject> alreadyExportedVolumes = (Map<String, VolHostIOObject>) keyMap .get(Constants.EXPORTED_VOLUMES); alreadyExportedVolumes.putAll(volToIolimits); } if (device.checkIfVmax3()) { // set the CoPs of SG's processed in the keyMap. // This list will be used as a reference to skip them to fetch unexported volume // SLO Names. if (!keyMap.containsKey(Constants.STORAGE_GROUPS_PROCESSED)) { keyMap.put(Constants.STORAGE_GROUPS_PROCESSED, processedSGCoPs); } else { List<CIMObjectPath> volumesWithFastPolicy = (List<CIMObjectPath>) keyMap .get(Constants.STORAGE_GROUPS_PROCESSED); volumesWithFastPolicy.addAll(processedSGCoPs); } // Set the volumesWithSLO in the keyMap for further processing. if (!keyMap.containsKey(Constants.VOLUMES_WITH_SLOS)) { keyMap.put(Constants.VOLUMES_WITH_SLOS, volToFastPolicy); } else { Map<String, String> volumesWithFastPolicy = (Map<String, String>) keyMap .get(Constants.VOLUMES_WITH_SLOS); volumesWithFastPolicy.putAll(volToFastPolicy); } } } catch (Exception e) { _logger.error("Extracting already exported Volumes failed", e); } } /** * get All Child SGs if cascaded * * @param path * @param client * @return */ private List<CIMObjectPath> getChildGroupsifCascaded(CIMObjectPath path, WBEMClient client) { CloseableIterator<CIMObjectPath> pathItr = null; List<CIMObjectPath> childSGs = new ArrayList<CIMObjectPath>(); try { pathItr = client.referenceNames(path, SmisConstants.SE_MEMBER_OF_COLLECTION_DMG_DMG, null); if (!pathItr.hasNext()) { // There are no references in this SG, it is a standalone. return Collections.emptyList(); } while (pathItr.hasNext()) { CIMObjectPath objPath = pathItr.next(); CIMProperty prop = objPath.getKey(SmisConstants.MEMBER); CIMObjectPath comparePath = (CIMObjectPath) prop.getValue(); if (comparePath.toString().endsWith(path.toString())) { return Collections.emptyList(); } _logger.debug("Found Child SG {}", comparePath.toString()); childSGs.add(comparePath); } } catch (Exception e) { _logger.info("Got exception trying to retrieve cascade status of SG. Assuming cascaded: ", e); } finally { if (null != pathItr) { pathItr.close(); } } return childSGs; } /** * Add IO limits on volume based on SG they belong to. * * Also sets the SLO name in which the SG is configured. * * @param client * @param path * @param volToIolimits * @param parentHostIoBw * @param parentHostIoPs */ private void addIoLimitsOnVolume(WBEMClient client, CIMObjectPath path, Map<String, VolHostIOObject> volToIolimits, Map<String, String> volToFastPolicy, String parentHostIoBw, String parentHostIoPs) { try { CIMInstance instance = client.getInstance(path, false, true, SmisConstants.PS_HOST_IO); String hostIoBw = String.valueOf(instance.getPropertyValue(SmisConstants.EMC_MAX_BANDWIDTH)); String hostIoPs = String.valueOf(instance.getPropertyValue(SmisConstants.EMC_MAX_IO)); String fastSetting = SmisUtils.getSLOPolicyName(instance); _logger.info("Bw {} and Iops {} found for SG : {} ", new Object[] { hostIoBw, hostIoPs, String.valueOf(instance.getPropertyValue(Constants.ELEMENTNAME)) }); if (hostIoBw.equals("0") && hostIoPs.equals("0")) { hostIoBw = parentHostIoBw; hostIoPs = parentHostIoPs; } CloseableIterator<CIMObjectPath> volPaths = client.associatorNames(path, null, Constants.STORAGE_VOLUME, null, null); while (volPaths.hasNext()) { CIMObjectPath volPath = volPaths.next(); String volumeNativeGuid = getVolumeNativeGuid(volPath); VolHostIOObject obj = new VolHostIOObject(); obj.setVolNativeGuid(volumeNativeGuid); obj.setHostIoBw(hostIoBw); obj.setHostIops(hostIoPs); _logger.debug("Volume key: {}..obj : {}", volumeNativeGuid, obj.toString()); volToIolimits.put(volumeNativeGuid, obj); if (!Strings.isNullOrEmpty(fastSetting)) { volToFastPolicy.put(volumeNativeGuid, fastSetting); } } } catch (Exception e) { _logger.warn("Finding HostIO limits failed during unmanaged volume discovery", e); } } @Override protected void setPrerequisiteObjects(List<Object> inputArgs) throws BaseCollectionException { _args = inputArgs; } }