/* * Copyright (c) 2008-2012 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.plugins.metering.vnxfile.processor; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.httpclient.methods.PostMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.DiscoveredDataObject.Type; import com.emc.storageos.db.client.model.FileShare; import com.emc.storageos.db.client.model.Stat; 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.plugins.metering.vnxfile.VNXFileConstants; import com.emc.storageos.plugins.metering.vnxfile.VNXFilePluginException; import com.emc.nas.vnxfile.xmlapi.FileSystemSetUsageStats; import com.emc.nas.vnxfile.xmlapi.FileSystemSetUsageStats.Item; import com.emc.nas.vnxfile.xmlapi.ResponsePacket; import com.emc.nas.vnxfile.xmlapi.Status; import com.emc.nas.vnxfile.xmlapi.Status.Problem; import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator; import com.emc.storageos.volumecontroller.impl.plugins.metering.CassandraInsertion; import com.emc.storageos.volumecontroller.impl.plugins.metering.ZeroRecordGenerator; import com.emc.storageos.volumecontroller.impl.plugins.metering.vnxfile.VNXFileProcessor; /** * FileshareUsageProcessor responsible to process the response received from the * XMLAPI server and parse the stream and populates the java objects. */ public class VNXFileSystemUsageProcessor extends VNXFileProcessor { /** * Logger instance. */ private final Logger _logger = LoggerFactory .getLogger(VNXFileSystemUsageProcessor.class); private ZeroRecordGenerator _zeroRecordGenerator; private CassandraInsertion _statsColumnInjector; @SuppressWarnings("unchecked") @Override public void processResult(Operation operation, Object resultObj, Map<String, Object> keyMap) throws BaseCollectionException { _logger.info("processing fileshare usage response" + resultObj); final PostMethod result = (PostMethod) resultObj; try { DbClient dbClient = (DbClient) keyMap.get(Constants.dbClient); ResponsePacket responsePacket = (ResponsePacket) _unmarshaller .unmarshal(result.getResponseBodyAsStream()); if (null != responsePacket.getPacketFault()) { Status status = responsePacket.getPacketFault(); List<Problem> problems = status.getProblem(); Iterator<Problem> problemsItr = problems.iterator(); while (problemsItr.hasNext()) { Problem problem = problemsItr.next(); _logger.error( "Fault response received due to {} possible cause {}", problem.getDescription(), problem.getDiagnostics()); } } else { List<Object> fsUsageInfo = getQueryStatsResponse(responsePacket); final List<Stat> statList = (List<Stat>) keyMap .get(Constants._Stats); processFileShareInfo(fsUsageInfo, keyMap, statList, dbClient); _zeroRecordGenerator.identifyRecordstobeZeroed(keyMap, statList, FileShare.class); } } catch (final IOException ioEx) { _logger.error( "IOException occurred while processing the Fileshare capacity response due to {}", ioEx.getMessage()); throw new VNXFilePluginException( "IOException occurred while processing the Fileshare capacity response.", ioEx.getCause()); } catch (final Exception ex) { _logger.error( "Exception occurred while processing the Fileshare capacity response due to {}", ex.getMessage()); throw new VNXFilePluginException( "Exception occurred while processing the Fileshare capacity response.", ex.getCause()); } finally { result.releaseConnection(); } } /** * process the FileShareUsage response of the VNX XML API Server. * * @param fsUsageList * : fileShareUsage map. * @param keyMap * : attribute map. * @param statList * : list of stat objects. */ @SuppressWarnings("rawtypes") private void processFileShareInfo(final List<Object> fsUsageList, final Map<String, Object> keyMap, final List<Stat> statList, DbClient dbClient) throws VNXFilePluginException { final String serialId = keyMap.get(Constants._serialID).toString(); Iterator iterator = fsUsageList.iterator(); keyMap.put(Constants._TimeCollected, System.currentTimeMillis()); Map<String, Long> fsCapacityMap = new HashMap<String, Long>(); while (iterator.hasNext()) { FileSystemSetUsageStats fsSetUsageStats = (FileSystemSetUsageStats) iterator.next(); List<Item> fsUsageItems = fsSetUsageStats.getItem(); _logger.info("Received {} fileShareUsage records at server time {}", fsUsageItems.size(), fsSetUsageStats.getTime()); for (Item item : fsUsageItems) { if (null == item.getFileSystem()) { continue; } final String nativeGuid = NativeGUIDGenerator.generateNativeGuid(Type.vnxfile.toString(), serialId, item.getFileSystem()); Stat stat = _zeroRecordGenerator.injectattr(keyMap, nativeGuid, null); if (null != stat) { stat.setTimeInMillis((Long) keyMap.get(Constants._TimeCollected)); stat.setTimeCollected((Long) keyMap.get(Constants._TimeCollected)); injectProvisionedCapacity(stat, keyMap); // The data coming in is in KB. Converting to Bytes stat.setAllocatedCapacity(item.getSpaceUsed() * 1024); _statsColumnInjector.injectColumns(stat, dbClient); statList.add(stat); // Persists the file system, only if change in used capacity. DbClient client = (DbClient) keyMap.get(Constants.dbClient); if (client != null) { FileShare fileSystem = client.queryObject(FileShare.class, stat.getResourceId()); if (fileSystem != null) { if (!fileSystem.getInactive() && fileSystem.getUsedCapacity() != stat.getAllocatedCapacity()) { fileSystem.setUsedCapacity(stat.getAllocatedCapacity()); client.persistObject(fileSystem); } } } } // filesystem and total capacity in Map long totalSpace =item.getSpaceTotal(); String fsNativeId = item.getFileSystem(); fsCapacityMap.put(fsNativeId, Long.valueOf(totalSpace)); _logger.info("processFileShareInfo - FileSystem native id {} and file system total size{}", fsNativeId, String.valueOf(totalSpace)); } _logger.info("Filesystems found - {} ", fsCapacityMap.size()); keyMap.put(VNXFileConstants.FILE_CAPACITY_MAP, fsCapacityMap); } _logger.info("No. of stat objects: {}", statList.size()); } /** * injects the ProvisionedCapacity from provisioning capacity. * * @param stat * @param keyMap */ private void injectProvisionedCapacity(final Stat stat, final Map<String, Object> keyMap) { final DbClient dbClient = (DbClient) keyMap.get(VNXFileConstants.DBCLIENT); try { final FileShare fileObj = dbClient.queryObject(FileShare.class, stat.getResourceId()); _logger.info("injectProvisioned Capacity existing {} from File System {}", stat.getProvisionedCapacity(), fileObj.getCapacity()); stat.setProvisionedCapacity(fileObj.getCapacity()); } catch (final Exception e) { _logger.error("No FileShare found using resource {}", stat.getResourceId()); } } // @Override protected void setPrerequisiteObjects(List<Object> inputArgs) throws VNXFilePluginException { } /** * set the cachesyncher. * * @param cachesync */ public void setZeroRecordGenerator(ZeroRecordGenerator recordGenerator) { _zeroRecordGenerator = recordGenerator; } public void setStatsColumnInjector(CassandraInsertion statsColumnInjector) { _statsColumnInjector = statsColumnInjector; } public CassandraInsertion getStatsColumnInjector() { return _statsColumnInjector; } }