package org.openstack.atlas.usagerefactor.collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openstack.atlas.service.domain.entities.Host;
import org.openstack.atlas.service.domain.entities.LoadBalancer;
import org.openstack.atlas.service.domain.events.UsageEvent;
import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException;
import org.openstack.atlas.service.domain.exceptions.UsageEventCollectionException;
import org.openstack.atlas.service.domain.repository.HostRepository;
import org.openstack.atlas.usagerefactor.SnmpUsage;
import org.openstack.atlas.usagerefactor.processor.UsageEventProcessor;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Component
public abstract class AbstractUsageEventCollection {
private final Log LOG = LogFactory.getLog(AbstractUsageEventCollection.class);
private ExecutorService executorService;
private UsageEventProcessor usageEventProcessor;
private HostRepository hostRepository;
public AbstractUsageEventCollection() throws UsageEventCollectionException {
}
@Required
public void setHostRepository(HostRepository hostRepository) {
this.hostRepository = hostRepository;
}
@Required
public void setUsageEventProcessor(UsageEventProcessor usageEventProcessor) {
this.usageEventProcessor = usageEventProcessor;
}
public abstract List<Future<SnmpUsage>> collectUsageRecords(ExecutorService executorService, UsageEventProcessor usageEventProcessor, List<Host> hosts, LoadBalancer lb) throws UsageEventCollectionException;
public abstract List<SnmpUsage> getUsagesFromFutures(List<Future<SnmpUsage>> futures) throws UsageEventCollectionException;
/**
* Used to process usage events
*
* @param lb
* @param event
* @param eventTime
* @throws UsageEventCollectionException
*/
public void collectUsageAndProcessUsageRecords(LoadBalancer lb, UsageEvent event, Calendar eventTime) throws UsageEventCollectionException {
LOG.debug("Processing Usage Records for load balancer: " + lb.getId());
List<SnmpUsage> usages = getUsage(lb);
usageEventProcessor.processUsageEvent(usages, lb, event, eventTime);
}
public List<SnmpUsage> getUsage(LoadBalancer lb) throws UsageEventCollectionException {
LOG.debug("Processing Usage Records for load balancer: " + lb.getId());
List<Host> hosts = null;
try {
hosts = gatherHostsData(lb);
} catch (EntityNotFoundException e) {
LOG.error(String.format("On an event, load balancer %d was assigned to host %d and it does not exist.", lb.getId(), lb.getHost().getId()));
}
List<SnmpUsage> usages;
if (hosts != null && !hosts.isEmpty()) {
executorService = Executors.newFixedThreadPool(hosts.size());
List<Future<SnmpUsage>> futures = collectUsageRecords(executorService, usageEventProcessor, hosts, lb);
usages = getUsagesFromFutures(futures);
LOG.debug("Finished getting snmp usage for: " + lb.getId());
} else {
LOG.error("Hosts data invalid, this shouldn't happen... Verify DB for data and notify developer immediately. ");
throw new UsageEventCollectionException("Hosts data invalid, please contact support.");
}
return usages;
}
/**
* Used to process events that will not have usage, such as Create event with specified hosts.
*
* @param lb
* @param event
* @param eventTime
* @throws UsageEventCollectionException
*/
public void processZeroUsageEvent(LoadBalancer lb, UsageEvent event, Calendar eventTime) throws UsageEventCollectionException {
List<Host> hosts = null;
try {
hosts = gatherHostsData(lb);
} catch (EntityNotFoundException e) {
LOG.error(String.format("On %s event, load balancer %d was assigned to host %d and it does not exist.", event.name(), lb.getId(), lb.getHost().getId()));
}
if (hosts != null && !hosts.isEmpty()) {
List<SnmpUsage> snmpUsages = new ArrayList<SnmpUsage>();
for (Host h : hosts) {
SnmpUsage snmpUsage = new SnmpUsage();
snmpUsage.setHostId(h.getId());
snmpUsage.setLoadbalancerId(lb.getId());
snmpUsage.setBytesIn(0L);
snmpUsage.setBytesInSsl(0L);
snmpUsage.setBytesOutSsl(0L);
snmpUsage.setBytesOut(0L);
snmpUsages.add(snmpUsage);
}
usageEventProcessor.processUsageEvent(snmpUsages, lb, event, eventTime);
} else {
LOG.error("Hosts data invalid, this shouldn't happen... Verify DB for data and notify developer immediately. ");
throw new UsageEventCollectionException("Hosts data invalid, please contact support.");
}
}
public void processUsageEvent(List<SnmpUsage> usages, LoadBalancer lb, UsageEvent event, Calendar eventTime) {
usageEventProcessor.processUsageEvent(usages, lb, event, eventTime);
}
private List<Host> gatherHostsData(LoadBalancer lb) throws EntityNotFoundException {
return hostRepository.getOnlineHostsByLoadBalancerHostCluster(lb);
}
}