/* * Copyright (c) 2008-2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.ibm.xiv; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.BlockSnapshot; 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.PartitionManager; 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; public class XIVStorageVolumeProcessor extends StorageProcessor { private Logger _logger = LoggerFactory .getLogger(XIVStorageVolumeProcessor.class); private static final String SOURCE_VOLUME_NAME = "SourceVolumeName"; private static final String VOLUME = "Volume"; private static final String BLOCK_SNAPSHOT = "BlockSnapshot"; private static final String VIRTUAL_SPACE_CONSUMED = "VirtualSpaceConsumed"; private static final String BLOCK_SIZE = "BlockSize"; private static final String CONSUMABLE_BLOCKS = "ConsumableBlocks"; private static final String SYSTEMNAME = "SystemName"; private static final String DEVICEID = "DeviceID"; private static final int BATCH_SIZE = 200; private DbClient _dbClient = null; private List<Volume> _updateVolumes = null; private List<BlockSnapshot> _updateSnapShots; private PartitionManager _partitionManager; public void setPartitionManager(PartitionManager partitionManager) { _partitionManager = partitionManager; } @Override public void processResult(Operation operation, Object resultObj, Map<String, Object> keyMap) throws BaseCollectionException { final Iterator<?> it = (Iterator<?>) resultObj; _dbClient = (DbClient) keyMap.get(Constants.dbClient); _updateVolumes = new ArrayList<Volume>(); _updateSnapShots = new ArrayList<BlockSnapshot>(); try { while (it.hasNext()) { CIMInstance volumeViewInstance = null; volumeViewInstance = (CIMInstance) it.next(); String nativeGuid = getVolumeViewNativeGuid(volumeViewInstance .getObjectPath()); String source = getCIMPropertyValue(volumeViewInstance, SOURCE_VOLUME_NAME); if (source != null && !source.isEmpty()) { BlockSnapshot snapShot = checkSnapShotExistsInDB( nativeGuid, _dbClient); if (snapShot == null || snapShot.getInactive()) { _logger.debug("Skipping unmanged snapshot {}", nativeGuid); continue; } _logger.debug("Snapshot managed by ViPR {}", nativeGuid); updateBlockSnapShot(volumeViewInstance, snapShot, nativeGuid); if (_updateSnapShots.size() > BATCH_SIZE) { _partitionManager.updateInBatches(_updateSnapShots, getPartitionSize(keyMap), _dbClient, BLOCK_SNAPSHOT); _updateSnapShots.clear(); } } else { Volume storageVolume = checkStorageVolumeExistsInDB( nativeGuid, _dbClient); if (storageVolume == null || storageVolume.getInactive()) { _logger.debug("Skipping unmanaged volume {}", nativeGuid); continue; } _logger.debug("Volume managed by ViPR {}", nativeGuid); updateStorageVolume(volumeViewInstance, storageVolume); } if (_updateVolumes.size() > BATCH_SIZE) { _partitionManager.updateInBatches(_updateVolumes, getPartitionSize(keyMap), _dbClient, VOLUME); _updateVolumes.clear(); } } // if list empty, this method returns back immediately. // partition size might not be used in this context, as batch size < // partition size. // TODO metering might need some extra work to push volumes in // batches, hence not changing this method signature _partitionManager.updateInBatches(_updateVolumes, getPartitionSize(keyMap), _dbClient, VOLUME); _partitionManager.updateInBatches(_updateSnapShots, getPartitionSize(keyMap), _dbClient, BLOCK_SNAPSHOT); } catch (Exception e) { _logger.error("Processing Volumes and Snapshots failed", e); } finally { _updateVolumes = null; _updateSnapShots = null; } } private void updateBlockSnapShot(CIMInstance volumeInstance, BlockSnapshot snapShot, String nativeGuid) { snapShot.setAllocatedCapacity(Long.parseLong(getCIMPropertyValue( volumeInstance, VIRTUAL_SPACE_CONSUMED))); snapShot.setProvisionedCapacity(returnProvisionedCapacity(volumeInstance)); _updateSnapShots.add(snapShot); } private void updateStorageVolume(CIMInstance volumeInstance, Volume storageVolume) throws IOException { storageVolume.setAllocatedCapacity(Long.parseLong(getCIMPropertyValue( volumeInstance, VIRTUAL_SPACE_CONSUMED))); storageVolume .setProvisionedCapacity(returnProvisionedCapacity(volumeInstance)); _updateVolumes.add(storageVolume); } private String getVolumeViewNativeGuid(CIMObjectPath path) { String systemName = path.getKey(SYSTEMNAME).getValue().toString(); String id = path.getKey(DEVICEID).getValue().toString(); // for snapshot or Volume , native Guid format is same return NativeGUIDGenerator.generateNativeGuidForVolumeOrBlockSnapShot( systemName.toUpperCase(), id); } private long returnProvisionedCapacity(CIMInstance volumeInstance) { long blocksize = Long.parseLong(volumeInstance.getPropertyValue( BLOCK_SIZE).toString()); long blocks = Long.parseLong(volumeInstance.getPropertyValue( CONSUMABLE_BLOCKS).toString()); return blocksize * blocks; } }