private boolean collectDirectNetworkUsage(final HostVO host) {
s_logger.debug("Direct Network Usage stats collector is running...");
final long zoneId = host.getDataCenterId();
final 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);
final 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() == Account.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);
}
}
final 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.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
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);
}
});
return true;
}