/* * Copyright (c) 2008-2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.detailedDiscovery; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.DiscoveredDataObject; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume; import com.emc.storageos.db.client.model.VirtualPool; import com.emc.storageos.db.client.model.Volume; 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.SMICommunicationInterface; 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; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import javax.cim.CIMProperty; import javax.wbem.client.WBEMClient; import java.net.URI; import java.util.Iterator; import java.util.List; import java.util.Map; /** * * StorageProcessor class to process data about meta type for a meta volume and set this data * in unmanaged volume instance. */ public class MetaVolumeTypeProcessor extends StorageProcessor { private Logger _logger = LoggerFactory.getLogger(MetaVolumeMembersProcessor.class); private static final String[] STRIPE_EXTENTS_NUMBER = new String[] { SmisConstants.CP_EXTENT_STRIPE_LENGTH }; private List<Object> _args; @Override public void processResult( Operation operation, Object resultObj, Map<String, Object> keyMap) throws BaseCollectionException { try { DbClient dbClient = (DbClient) keyMap.get(Constants.dbClient); WBEMClient client = SMICommunicationInterface.getCIMClient(keyMap); CIMObjectPath metaVolumePath = getObjectPathfromCIMArgument(_args); _logger.info(String.format("Processing EMC_Meta for meta volume: %s", metaVolumePath)); UnManagedVolume preExistingVolume = null; String isMetaVolume = "true"; String nativeGuid; // Check if storage volume exists in db (the method is called from re-discovery context). nativeGuid = getVolumeNativeGuid(metaVolumePath); Volume storageVolume = checkStorageVolumeExistsInDB(nativeGuid, dbClient); if (null == storageVolume || storageVolume.getInactive()) { // Check if unmanaged volume exists in db (the method is called from unmanaged volumes discovery context). nativeGuid = getUnManagedVolumeNativeGuidFromVolumePath(metaVolumePath); _logger.debug("Meta volume nativeguid :" + nativeGuid); preExistingVolume = checkUnManagedVolumeExistsInDB(nativeGuid, dbClient); if (null == preExistingVolume) { _logger.debug("Volume Info Object not found :" + nativeGuid); return; } isMetaVolume = preExistingVolume.getVolumeCharacterstics(). get(UnManagedVolume.SupportedVolumeCharacterstics.IS_METAVOLUME.toString()); } else { _logger.debug("Volume managed by Bourne :" + storageVolume.getNativeGuid()); isMetaVolume = storageVolume.getIsComposite().toString(); } if (isMetaVolume.equalsIgnoreCase("false")) { _logger.error(String.format("MetaVolumeTypeProcessor called for regular volume: %s", nativeGuid)); return; } final Iterator<?> it = (Iterator<?>) resultObj; if (it.hasNext()) { final CIMObjectPath symmMetaPath = (CIMObjectPath) it.next(); _logger.debug(String.format("Processing EMC_Meta: %s", symmMetaPath)); CIMInstance cimMeta = client.getInstance(symmMetaPath, false, false, STRIPE_EXTENTS_NUMBER); CIMProperty stripeLengthProperty = cimMeta.getProperty(SmisConstants.CP_EXTENT_STRIPE_LENGTH); Long stripeLength = Long.valueOf(stripeLengthProperty.getValue().toString()); String metaVolumeType; if (stripeLength < 1) { _logger.error(String.format("Stripe length for EMC_Meta is less than 1: %s", stripeLength)); return; } else if (stripeLength == 1) { // this is concatenated meta volume _logger.debug(String.format("Stripe length for EMC_Meta is : %s. Type is concatenated.", stripeLength)); metaVolumeType = Volume.CompositionType.CONCATENATED.toString(); } else { // this is striped meta volume _logger.debug(String.format("Stripe length for EMC_Meta is : %s. Type is striped.", stripeLength)); metaVolumeType = Volume.CompositionType.STRIPED.toString(); } _logger.info(String.format("Meta volume: %s, type: %s", metaVolumePath, metaVolumeType)); if (null == preExistingVolume) { // storage volume update storageVolume.setCompositionType(metaVolumeType); // persist volume in db dbClient.persistObject(storageVolume); } else { // unmanaged volume update StringSet metaVolumeTypeSet = new StringSet(); metaVolumeTypeSet.add(metaVolumeType); preExistingVolume.putVolumeInfo(UnManagedVolume.SupportedVolumeInformation.META_VOLUME_TYPE.toString(), metaVolumeTypeSet); // If meta volume is striped vmax volume, make sure that we remove vpools with fast expansion from matched vpool list // for this volume. if (Volume.CompositionType.STRIPED.toString().equalsIgnoreCase(metaVolumeType)) { URI storageSystemUri = preExistingVolume.getStorageSystemUri(); StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, storageSystemUri); if (DiscoveredDataObject.Type.vmax.toString().equalsIgnoreCase(storageSystem.getSystemType())) { _logger.info("Check matched vpool list for vmax striped meta volume and remove fastExpansion vpools."); StringSet matchedVirtualPools = preExistingVolume.getSupportedVpoolUris(); if (matchedVirtualPools != null && !matchedVirtualPools.isEmpty()) { _logger.debug("Matched Pools :" + Joiner.on("\t").join(matchedVirtualPools)); StringSet newMatchedPools = new StringSet(); boolean needToReplace = false; for (String vPoolUriStr : matchedVirtualPools) { URI vPoolUri = new URI(vPoolUriStr); VirtualPool virtualPool = dbClient.queryObject(VirtualPool.class, vPoolUri); // null check since supported vPool list in UnManagedVolume may contain inactive vPool if (virtualPool != null && !virtualPool.getFastExpansion()) { newMatchedPools.add(vPoolUriStr); } else { needToReplace = true; } } if (needToReplace) { matchedVirtualPools.replace(newMatchedPools); _logger.info("Replaced VPools : {}", Joiner.on("\t").join(preExistingVolume.getSupportedVpoolUris())); } } } } // persist volume in db dbClient.updateAndReindexObject(preExistingVolume); } } } catch (Exception e) { _logger.error("Processing meta volume type information failed :", e); } } @Override protected void setPrerequisiteObjects(List<Object> inputArgs) throws BaseCollectionException { _args = inputArgs; } }