/** * Copyright (c) 2015 EMC Corporation * All Rights Reserved * * This software contains the intellectual property of EMC Corporation * or is licensed to EMC Corporation from third parties. Use of this * software and the intellectual property contained therein is expressly * limited to the terms and conditions of the License Agreement under which * it is provided by or on behalf of EMC. */ package com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.detailedDiscovery; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import javax.cim.UnsignedInteger32; import javax.wbem.CloseableIterator; import javax.wbem.client.EnumerateResponse; import javax.wbem.client.WBEMClient; import com.emc.storageos.volumecontroller.impl.plugins.SMICommunicationInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.StoragePool; 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.NativeGUIDGenerator; import com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.StorageProcessor; import com.emc.storageos.volumecontroller.impl.smis.SmisConstants; import com.google.common.base.Joiner; /** * Processor used in getting bound storage volumes for VMAX2 Thin pool. * * A VMAX2 FAST thin volume may be associated with more than one storage pool. * one is bound pool where it is originally created from, and the others are because of data movement due to auto-tiering policy. * With the bound volumes list for each thin pool, skip the non-bound volumes in StorageVolumeInfoProcessor while creating UnManaged * Volumes. * */ public class StorageVolumeBoundPoolProcessor extends StorageProcessor { private Logger _logger = LoggerFactory.getLogger(StorageVolumeBoundPoolProcessor.class); private List<Object> _args; private DbClient _dbClient; @Override public void processResult(Operation operation, Object resultObj, Map<String, Object> keyMap) throws BaseCollectionException { CloseableIterator<CIMInstance> allocatedFromStoragePoolInstances = null; EnumerateResponse<CIMInstance> allocatedFromStoragePoolInstanceChunks = null; @SuppressWarnings("unchecked") Map<String, Set<String>> vmax2ThinPoolToBoundVolumesMap = (Map<String, Set<String>>) keyMap .get(Constants.VMAX2_THIN_POOL_TO_BOUND_VOLUMES); _dbClient = (DbClient) keyMap.get(Constants.dbClient); WBEMClient client = SMICommunicationInterface.getCIMClient(keyMap); CIMObjectPath storagePoolPath = null; try { storagePoolPath = getObjectPathfromCIMArgument(_args); _logger.debug("VMAX2 Thin Pool: {}", storagePoolPath.toString()); String poolNativeGuid = NativeGUIDGenerator.generateNativeGuidForPool(storagePoolPath); StoragePool pool = checkStoragePoolExistsInDB(poolNativeGuid, _dbClient); if (pool == null) { _logger.error( "Skipping unmanaged volume discovery as the storage pool with path {} doesn't exist in ViPR", storagePoolPath.toString()); return; } Set<String> boundVolumes = new HashSet<String>(); allocatedFromStoragePoolInstanceChunks = (EnumerateResponse<CIMInstance>) resultObj; allocatedFromStoragePoolInstances = allocatedFromStoragePoolInstanceChunks.getResponses(); processVolumes(allocatedFromStoragePoolInstances, boundVolumes); while (!allocatedFromStoragePoolInstanceChunks.isEnd()) { _logger.info("Processing Next Volume Chunk of size {}", BATCH_SIZE); allocatedFromStoragePoolInstanceChunks = client.getInstancesWithPath(storagePoolPath, allocatedFromStoragePoolInstanceChunks.getContext(), new UnsignedInteger32(BATCH_SIZE)); processVolumes(allocatedFromStoragePoolInstanceChunks.getResponses(), boundVolumes); } vmax2ThinPoolToBoundVolumesMap.put(storagePoolPath.toString(), boundVolumes); _logger.debug("Bound volumes list {}", Joiner.on("\t").join(boundVolumes)); } catch (Exception e) { _logger.error("Processing Bound Storage Volume Information failed :", e); } finally { if (null != allocatedFromStoragePoolInstances) { allocatedFromStoragePoolInstances.close(); } if (null != allocatedFromStoragePoolInstanceChunks) { try { client.closeEnumeration(storagePoolPath, allocatedFromStoragePoolInstanceChunks.getContext()); } catch (Exception e) { _logger.debug("Exception occurred while closing enumeration", e); } } } } private void processVolumes(CloseableIterator<CIMInstance> allocatedFromStoragePoolInstances, Set<String> volumesList) { while (allocatedFromStoragePoolInstances.hasNext()) { CIMInstance allocatedFromStoragePoolInstance = allocatedFromStoragePoolInstances.next(); String boundToThinStoragePool = allocatedFromStoragePoolInstance.getPropertyValue(SmisConstants.EMC_BOUND_TO_THIN_STORAGE_POOL) .toString(); if (Boolean.valueOf(boundToThinStoragePool)) { String volume = allocatedFromStoragePoolInstance.getPropertyValue(SmisConstants.CP_DEPENDENT).toString(); CIMObjectPath volumePath = new CIMObjectPath(volume); String deviceId = volumePath.getKey(DEVICE_ID).getValue().toString(); volumesList.add(deviceId); } } } @Override protected void setPrerequisiteObjects(List<Object> inputArgs) throws BaseCollectionException { _args = inputArgs; } }