private DirectNetworkUsageAnswer getPublicIpBytesSentAndReceived(DirectNetworkUsageCommand cmd) throws ExecutionException { DirectNetworkUsageAnswer answer = new DirectNetworkUsageAnswer(cmd); try { // Direct Network Usage URL trafficSentinel; try { // Query traffic Sentinel trafficSentinel = new URL( _url + "/inmsf/Query?script=" + URLEncoder.encode( getScript(cmd.getPublicIps(), cmd.getStart(), cmd.getEnd()), "UTF-8") + "&authenticate=basic&resultFormat=txt"); BufferedReader in = new BufferedReader(new InputStreamReader(trafficSentinel.openStream())); String inputLine; while ((inputLine = in.readLine()) != null) { // Parse the script output StringTokenizer st = new StringTokenizer(inputLine, ","); if (st.countTokens() == 3) { String publicIp = st.nextToken(); Long bytesSent = new Long(st.nextToken()); Long bytesRcvd = new Long(st.nextToken()); if (bytesSent == null || bytesRcvd == null) { s_logger.debug("Incorrect bytes for IP: " + publicIp); } long[] bytesSentAndReceived = new long[2]; bytesSentAndReceived[0] = bytesSent; bytesSentAndReceived[1] = bytesRcvd; answer.put(publicIp, bytesSentAndReceived); } } in.close(); } catch (MalformedURLException e1) { s_logger.info("Invalid Traffic Sentinel URL", e1); throw new ExecutionException(e1.getMessage()); } catch (IOException e) { s_logger.debug("Error in direct network usage accounting", e); throw new ExecutionException(e.getMessage()); } } catch (Exception e) { s_logger.debug(e); throw new ExecutionException(e.getMessage()); } return answer; }
private boolean collectDirectNetworkUsage(HostVO host) { s_logger.debug("Direct Network Usage stats collector is running..."); long zoneId = host.getDataCenterId(); DetailVO lastCollectDetail = _detailsDao.findDetail(host.getId(), "last_collection"); if (lastCollectDetail == null) { s_logger.warn( "Last collection time not available. Skipping direct usage collection for Traffic Monitor: " + host.getId()); return false; } Date lastCollection = new Date(new Long(lastCollectDetail.getValue())); // Get list of IPs currently allocated List<IPAddressVO> allocatedIps = listAllocatedDirectIps(zoneId); Calendar rightNow = Calendar.getInstance(); // Allow 2 hours for traffic sentinel to populate historical traffic // This coule be made configurable rightNow.add(Calendar.HOUR_OF_DAY, -2); Date now = rightNow.getTime(); if (lastCollection.after(now)) { s_logger.debug( "Current time is less than 2 hours after last collection time : " + lastCollection.toString() + ". Skipping direct network usage collection"); return false; } // Get IP Assign/Release events from lastCollection time till now List<UsageEventVO> IpEvents = _eventDao.listDirectIpEvents(lastCollection, now, zoneId); Map<String, Date> ipAssigment = new HashMap<String, Date>(); List<UsageIPAddressVO> IpPartialUsage = new ArrayList< UsageIPAddressVO>(); // Ips which were allocated only for the part of collection // duration List<UsageIPAddressVO> fullDurationIpUsage = new ArrayList< UsageIPAddressVO>(); // Ips which were allocated only for the entire collection // duration // Use UsageEvents to track the IP assignment // Add them to IpUsage list with account_id , ip_address, alloc_date, release_date for (UsageEventVO IpEvent : IpEvents) { String address = IpEvent.getResourceName(); if (EventTypes.EVENT_NET_IP_ASSIGN.equals(IpEvent.getType())) { ipAssigment.put(address, IpEvent.getCreateDate()); } else if (EventTypes.EVENT_NET_IP_RELEASE.equals(IpEvent.getType())) { if (ipAssigment.containsKey(address)) { Date assigned = ipAssigment.get(address); ipAssigment.remove(address); IpPartialUsage.add( new UsageIPAddressVO( IpEvent.getAccountId(), address, assigned, IpEvent.getCreateDate())); } else { // Ip was assigned prior to lastCollection Date IpPartialUsage.add( new UsageIPAddressVO( IpEvent.getAccountId(), address, lastCollection, IpEvent.getCreateDate())); } } } List<String> IpList = new ArrayList<String>(); for (IPAddressVO ip : allocatedIps) { if (ip.getAllocatedToAccountId() == AccountVO.ACCOUNT_ID_SYSTEM) { // Ignore usage for system account continue; } String address = (ip.getAddress()).toString(); if (ipAssigment.containsKey(address)) { // Ip was assigned during the current period but not release till Date now IpPartialUsage.add( new UsageIPAddressVO( ip.getAllocatedToAccountId(), address, ipAssigment.get(address), now)); } else { // Ip was not assigned or released during current period. Consider entire duration for // usage calculation (lastCollection to now) fullDurationIpUsage.add( new UsageIPAddressVO(ip.getAllocatedToAccountId(), address, lastCollection, now)); // Store just the Ips to send the list as part of DirectNetworkUsageCommand IpList.add(address); } } List<UserStatisticsVO> collectedStats = new ArrayList<UserStatisticsVO>(); // Get usage for Ips which were assigned for the entire duration if (fullDurationIpUsage.size() > 0) { DirectNetworkUsageCommand cmd = new DirectNetworkUsageCommand(IpList, lastCollection, now, _TSinclZones, _TSexclZones); DirectNetworkUsageAnswer answer = (DirectNetworkUsageAnswer) _agentMgr.easySend(host.getId(), cmd); if (answer == null || !answer.getResult()) { String details = (answer != null) ? answer.getDetails() : "details unavailable"; String msg = "Unable to get network usage stats from " + host.getId() + " due to: " + details + "."; s_logger.error(msg); return false; } else { for (UsageIPAddressVO usageIp : fullDurationIpUsage) { String publicIp = usageIp.getAddress(); long[] bytesSentRcvd = answer.get(publicIp); Long bytesSent = bytesSentRcvd[0]; Long bytesRcvd = bytesSentRcvd[1]; if (bytesSent == null || bytesRcvd == null) { s_logger.debug("Incorrect bytes for IP: " + publicIp); continue; } if (bytesSent == 0L && bytesRcvd == 0L) { s_logger.trace("Ignore zero bytes for IP: " + publicIp); continue; } UserStatisticsVO stats = new UserStatisticsVO(usageIp.getAccountId(), zoneId, null, null, null, null); stats.setCurrentBytesSent(bytesSent); stats.setCurrentBytesReceived(bytesRcvd); collectedStats.add(stats); } } } // Get usage for Ips which were assigned for part of the duration period for (UsageIPAddressVO usageIp : IpPartialUsage) { IpList = new ArrayList<String>(); IpList.add(usageIp.getAddress()); DirectNetworkUsageCommand cmd = new DirectNetworkUsageCommand( IpList, usageIp.getAssigned(), usageIp.getReleased(), _TSinclZones, _TSexclZones); DirectNetworkUsageAnswer answer = (DirectNetworkUsageAnswer) _agentMgr.easySend(host.getId(), cmd); if (answer == null || !answer.getResult()) { String details = (answer != null) ? answer.getDetails() : "details unavailable"; String msg = "Unable to get network usage stats from " + host.getId() + " due to: " + details + "."; s_logger.error(msg); return false; } else { String publicIp = usageIp.getAddress(); long[] bytesSentRcvd = answer.get(publicIp); Long bytesSent = bytesSentRcvd[0]; Long bytesRcvd = bytesSentRcvd[1]; if (bytesSent == null || bytesRcvd == null) { s_logger.debug("Incorrect bytes for IP: " + publicIp); continue; } if (bytesSent == 0L && bytesRcvd == 0L) { s_logger.trace("Ignore zero bytes for IP: " + publicIp); continue; } UserStatisticsVO stats = new UserStatisticsVO(usageIp.getAccountId(), zoneId, null, null, null, null); stats.setCurrentBytesSent(bytesSent); stats.setCurrentBytesReceived(bytesRcvd); collectedStats.add(stats); } } if (collectedStats.size() == 0) { s_logger.debug("No new direct network stats. No need to persist"); return false; } // Persist all the stats and last_collection time in a single transaction Transaction txn = Transaction.open(Transaction.CLOUD_DB); try { txn.start(); for (UserStatisticsVO stat : collectedStats) { UserStatisticsVO stats = _statsDao.lock( stat.getAccountId(), stat.getDataCenterId(), 0L, null, host.getId(), "DirectNetwork"); if (stats == null) { stats = new UserStatisticsVO( stat.getAccountId(), zoneId, null, host.getId(), "DirectNetwork", 0L); stats.setCurrentBytesSent(stat.getCurrentBytesSent()); stats.setCurrentBytesReceived(stat.getCurrentBytesReceived()); _statsDao.persist(stats); } else { stats.setCurrentBytesSent(stats.getCurrentBytesSent() + stat.getCurrentBytesSent()); stats.setCurrentBytesReceived( stats.getCurrentBytesReceived() + stat.getCurrentBytesReceived()); _statsDao.update(stats.getId(), stats); } } lastCollectDetail.setValue("" + now.getTime()); _detailsDao.update(lastCollectDetail.getId(), lastCollectDetail); txn.commit(); } finally { txn.close(); } return true; }