package org.openstack.atlas.service.domain.services.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openstack.atlas.docs.loadbalancers.api.management.v1.ZeusRateLimitedLoadBalancer;
import org.openstack.atlas.lb.helpers.ipstring.IPv4Range;
import org.openstack.atlas.lb.helpers.ipstring.IPv4Ranges;
import org.openstack.atlas.lb.helpers.ipstring.IPv4ToolSet;
import org.openstack.atlas.lb.helpers.ipstring.exceptions.IPBlocksOverLapException;
import org.openstack.atlas.lb.helpers.ipstring.exceptions.IPOctetOutOfRangeException;
import org.openstack.atlas.lb.helpers.ipstring.exceptions.IPRangeTooBigException;
import org.openstack.atlas.lb.helpers.ipstring.exceptions.IPStringConversionException;
import org.openstack.atlas.service.domain.entities.*;
import org.openstack.atlas.service.domain.exceptions.BadRequestException;
import org.openstack.atlas.service.domain.exceptions.ClusterStatusException;
import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException;
import org.openstack.atlas.service.domain.exceptions.NoAvailableClusterException;
import org.openstack.atlas.service.domain.pojos.LoadBalancerCountByAccountIdClusterId;
import org.openstack.atlas.service.domain.pojos.VirtualIpAvailabilityReport;
import org.openstack.atlas.service.domain.pojos.VirtualIpBlock;
import org.openstack.atlas.service.domain.pojos.VirtualIpBlocks;
import org.openstack.atlas.service.domain.services.ClusterService;
import org.openstack.atlas.service.domain.services.TicketService;
import org.openstack.atlas.service.domain.services.VirtualIpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
public class ClusterServiceImpl extends BaseService implements ClusterService {
private final Log LOG = LogFactory.getLog(ClusterServiceImpl.class);
@Autowired
private VirtualIpService virtualIpService;
@Autowired
private TicketService ticketService;
@Override
public Cluster get(Integer clusterId) throws EntityNotFoundException {
return clusterRepository.getById(clusterId);
}
@Override
public Cluster getActiveCluster(Integer accountId) throws EntityNotFoundException, ClusterStatusException, NoAvailableClusterException {
return clusterRepository.getActiveCluster(accountId);
}
@Override
public List<Cluster> getAll() {
return clusterRepository.getAll();
}
@Override
public List<LoadBalancerCountByAccountIdClusterId> getAccountsInCluster(Integer clusterId) {
return clusterRepository.getAccountsInCluster(clusterId);
}
@Override
public List<Host> getHosts(Integer clusterId) {
return clusterRepository.getHosts(clusterId);
}
@Override
public List<VirtualIp> getVirtualIps(Integer id, Integer offset, Integer limit) {
return clusterRepository.getVirtualIps(id, offset, limit);
}
@Override
@Transactional
public List<ZeusRateLimitedLoadBalancer> getRateLimitedLoadBalancersInCluster(Integer clusterId) throws EntityNotFoundException {
List<Host> hostList = clusterRepository.getHosts(clusterId);
List<Integer> lbids = rateLimitRepository.getAllRateLimitedLoadBalancerIds();
List<LoadBalancer> lblist = new ArrayList();
List<ZeusRateLimitedLoadBalancer> zeusRateLimitedLoadBalancerList = new ArrayList();
ZeusRateLimitedLoadBalancer zeusRateLimitedLoadBalancer;
for (Integer lbId : lbids) {
lblist.add(loadBalancerRepository.getById(lbId));
}
for (LoadBalancer lb : lblist) {
for (Host host : hostList) {
if (lb.getHost().getId() == host.getId()) {
zeusRateLimitedLoadBalancer = new ZeusRateLimitedLoadBalancer();
zeusRateLimitedLoadBalancer.setAccountId(lb.getAccountId());
zeusRateLimitedLoadBalancer.setLoadbalancerId(lb.getId());
zeusRateLimitedLoadBalancer.setExpirationTime(lb.getRateLimit().getExpirationTime().getTime().toString());
zeusRateLimitedLoadBalancer.setTickets(ticketService.customTicketMapper(loadBalancerRepository.getTickets(lb.getId())));
zeusRateLimitedLoadBalancerList.add(zeusRateLimitedLoadBalancer);
}
}
}
return zeusRateLimitedLoadBalancerList;
}
@Override
@Transactional
public List<AccountGroup> getAPIRateLimitedAccounts(Integer clusterId) throws EntityNotFoundException {
List<AccountGroup> rateLimitedAccounts = groupRepository.getAllAccounts();
List<AccountGroup> returnedGroups = new ArrayList();
for (AccountGroup ag : rateLimitedAccounts) {
if (clusterRepository.isAccountInCluster(clusterId, ag.getAccountId())) {
//add to list
returnedGroups.add(ag);
}
}
return returnedGroups;
}
@Override
public Integer getNumberOfUniqueAccountsForCluster(Integer id) {
return clusterRepository.getNumberOfUniqueAccountsForCluster(id);
}
@Override
public Integer getNumberOfActiveLoadBalancersForCluster(Integer id) {
return clusterRepository.getNumberOfActiveLoadBalancersForCluster(id);
}
@Override
public List<VirtualIpAvailabilityReport> getVirtualIpAvailabilityReport(Integer clusterId) {
return clusterRepository.getVirtualIpAvailabilityReport(clusterId);
}
@Override
@Transactional
public VirtualIpBlocks addVirtualIpBlocks(VirtualIpBlocks vipBlocks, Integer clusterId) throws BadRequestException, IPStringConversionException, IPBlocksOverLapException, IPRangeTooBigException, IPOctetOutOfRangeException, EntityNotFoundException {
LOG.debug("Entering " + getClass());
Set<LoadBalancerJoinVip> vips = new HashSet<LoadBalancerJoinVip>();
VirtualIp vip;
IPv4Ranges ranges = new IPv4Ranges();
VirtualIpType vipType = vipBlocks.getType();
long ip;
int lowerOctet;
Cluster cluster = clusterRepository.getClusterById(clusterId);
for (VirtualIpBlock ipBlock : vipBlocks.getVirtualIpBlocks()) {
ranges.add(ipBlock.getFirstIp(), ipBlock.getLastIp());
} // Will throw an Exception if an IP block is invalid;
for (IPv4Range range : ranges.getRanges()) {
for (ip = range.getLo(); ip <= range.getHi(); ip++) {
vip = new VirtualIp();
vip.setIpAddress(IPv4ToolSet.long2ip(ip));
vip.setVipType(vipType);
vip.setCluster(cluster);
vip.setAllocated(false);
if (testForDuplicatesByCluster(vip, clusterId)) {
LOG.warn("Duplicate vips detected");
throw new BadRequestException(String.format("IP addresses must be unique within a cluster: Ip is duplicated: %s", vip.getIpAddress()));
}
LOG.info(String.format("calling persist for %s\n", vip.getIpAddress()));
virtualIpService.persist(vip);
LoadBalancerJoinVip loadBalancerJoinVip = new LoadBalancerJoinVip();
loadBalancerJoinVip.setVirtualIp(vip);
vips.add(loadBalancerJoinVip);
}
}
return vipBlocks;
}
private boolean testForDuplicatesByCluster(VirtualIp vip, Integer clusterId) {
List<VirtualIp> dbVips = virtualIpService.getVipsByClusterId(clusterId);
for (VirtualIp nvip : dbVips) {
if (vip.getIpAddress().equals(nvip.getIpAddress())) {
return true;
}
}
return false;
}
}