package org.openstack.atlas.service.domain.repository;
import org.openstack.atlas.service.domain.entities.*;
import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException;
import org.openstack.atlas.service.domain.exceptions.ServiceUnavailableException;
import org.openstack.atlas.service.domain.util.Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.*;
import javax.persistence.criteria.*;
import java.util.*;
@Repository
@Transactional
public class VirtualIpv6Repository {
final Log LOG = LogFactory.getLog(ClusterRepository.class);
@PersistenceContext(unitName = "loadbalancing")
private EntityManager entityManager;
public VirtualIpv6 getById(Integer id) throws EntityNotFoundException {
VirtualIpv6 vip = entityManager.find(VirtualIpv6.class, id);
if (vip == null) {
String message = Constants.VirtualIpNotFound;
LOG.warn(message);
throw new EntityNotFoundException(message);
}
return vip;
}
public List<Integer> getAccountIdsAlreadyShaHashed() {
return entityManager.createQuery("select a.id from Account a").getResultList();
}
public Account getAccountRecordById(Integer aid) throws EntityNotFoundException {
Account account;
if (aid == null) {
throw new EntityNotFoundException("Refusing to lookup account with null id");
}
account = entityManager.find(Account.class, aid);
if (account == null) {
throw new EntityNotFoundException("Account id " + aid.toString() + " not found");
}
return account;
}
public List<Integer> getAccountIds() {
return entityManager.createQuery("select distinct(lb.accountId) from LoadBalancer lb").getResultList();
}
public VirtualIpv6 getByAccountIdVipOctets(Integer accountId, Integer vipOctets) throws EntityNotFoundException {
List<VirtualIpv6> v6List;
String qStr = "SELECT v from VirtualIpv6 v where accountId=:aid and vipOctets=:vo";
Query q = entityManager.createQuery(qStr);
q.setParameter("aid", accountId);
q.setParameter("vo", vipOctets);
v6List = q.getResultList();
if (v6List.size() != 1) {
String format = "Vip not found for accountId=%d and vipOctets=%d\n";
String msg = String.format(format, accountId, vipOctets);
throw new EntityNotFoundException(msg);
}
return null;
}
public Integer getNextVipOctet(Integer accountId) {
List<Integer> maxList;
Integer max;
int retry_count = 3;
String qStr = "SELECT max(v.vipOctets) from VirtualIpv6 v where v.accountId=:aid";
while (retry_count > 0) {
retry_count--;
try {
maxList = entityManager.createQuery(qStr).setLockMode(LockModeType.PESSIMISTIC_WRITE).setParameter("aid", accountId).getResultList();
max = maxList.get(0);
if (max == null) {
max = 0;
}
max++; // The next VipOctet
return max;
} catch (PersistenceException e) {
LOG.warn(String.format("Deadlock detected. %d retries left.", retry_count));
if (retry_count <= 0) {
throw e;
}
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
throw new ServiceUnavailableException("Too many create requests received. Please try again in a few moments.");
}
public Set<VirtualIpv6> getVirtualIpv6sByLoadBalancerId(Integer lid) {
String qStr = "SELECT j.virtualIp from LoadBalancerJoinVip6 j where j.loadBalancer.id = :lid";
Query q = entityManager.createQuery(qStr).setParameter("lid", lid);
return new HashSet<VirtualIpv6>(q.getResultList());
}
public List<VirtualIpv6> getVips6ByAccountId(Integer accountId) {
List<VirtualIpv6> vips;
String query = "select distinct(j.virtualIp) from LoadBalancerJoinVip6 j where j.loadBalancer.accountId = :accountId";
// String query = "select distinct l.virtualIps from LoadBalancer l where l.accountId = :accountId";
vips = entityManager.createQuery(query).setParameter("accountId", accountId).getResultList();
return vips;
}
public void persist(Object v) {
entityManager.persist(v);
}
public void merge(Object v) {
entityManager.merge(v);
}
public void remove(Object v) {
entityManager.remove(v);
}
public void flush() {
entityManager.flush();
}
public List<LoadBalancer> getLoadBalancersByVipId(Integer virtualIpv6Id) {
List<LoadBalancer> lbs;
String qStr = "select v.loadBalancer from LoadBalancerJoinVip6 "
+ "v where v.virtualIp.id=:vid";
Query q = entityManager.createQuery(qStr);
q.setParameter("vid", virtualIpv6Id);
return q.getResultList();
}
public Map<Integer, List<LoadBalancer>> getPorts(Integer vid) {
Map<Integer, List<LoadBalancer>> map = new TreeMap<Integer, List<LoadBalancer>>();
List<Object> hResults;
String query = "select j.virtualIp.id, j.loadBalancer.id, j.loadBalancer.accountId, j.loadBalancer.port "
+ "from LoadBalancerJoinVip6 j where j.virtualIp.id = :vid order by j.loadBalancer.port, j.loadBalancer.id";
hResults = entityManager.createQuery(query).setLockMode(LockModeType.PESSIMISTIC_READ)
.setParameter("vid", vid).getResultList();
for (Object r : hResults) {
Object[] row = (Object[]) r;
Integer port = (Integer) row[3];
if (!map.containsKey(port)) {
map.put(port, new ArrayList<LoadBalancer>());
}
LoadBalancer lb = new LoadBalancer();
lb.setId((Integer) row[1]);
lb.setAccountId((Integer) row[2]);
lb.setPort((Integer) row[3]);
map.get(port).add(lb);
int sslPort = getSslPorts((Integer) row[1]);
if ((sslPort != -1) && !map.containsKey(sslPort)) {
map.put(sslPort, new ArrayList<LoadBalancer>());
LoadBalancer lbssl = new LoadBalancer();
lbssl.setId((Integer) row[1]);
lbssl.setAccountId((Integer) row[2]);
lbssl.setPort((Integer) row[3]);
map.get(sslPort).add(lbssl);
}
}
return map;
}
public int getSslPorts(Integer lbId) {
Map<Integer, List<LoadBalancer>> map = new TreeMap<Integer, List<LoadBalancer>>();
List<Object> hResults;
String query = "select j.securePort "
+ "from SslTermination j where j.loadbalancer.id = :lbId";
hResults = entityManager.createQuery(query).setParameter("lbId", lbId).getResultList();
if (hResults == null || hResults.isEmpty()) {
return -1;
}
return (Integer) hResults.get(0);
}
public void removeJoinRecord(LoadBalancerJoinVip6 loadBalancerJoinVip6) {
loadBalancerJoinVip6 = entityManager.find(LoadBalancerJoinVip6.class, loadBalancerJoinVip6.getId());
VirtualIpv6 virtualIpv6 = entityManager.find(VirtualIpv6.class, loadBalancerJoinVip6.getVirtualIp().getId());
virtualIpv6.getLoadBalancerJoinVip6Set().remove(loadBalancerJoinVip6);
entityManager.remove(loadBalancerJoinVip6);
}
public void deleteVirtualIp(VirtualIpv6 virtualIpv6) {
virtualIpv6 = entityManager.find(VirtualIpv6.class, virtualIpv6.getId());
entityManager.remove(virtualIpv6);
LOG.info(String.format("IPv6 virtual Ip '%d' deleted.", virtualIpv6.getId()));
}
public List<LoadBalancerJoinVip6> getJoinRecordsForVip(VirtualIpv6 virtualIp) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<LoadBalancerJoinVip6> criteria = builder.createQuery(LoadBalancerJoinVip6.class);
Root<LoadBalancerJoinVip6> lbJoinVipRoot = criteria.from(LoadBalancerJoinVip6.class);
Predicate hasVip = builder.equal(lbJoinVipRoot.get(LoadBalancerJoinVip6_.virtualIp), virtualIp);
criteria.select(lbJoinVipRoot);
criteria.where(hasVip);
return entityManager.createQuery(criteria).setLockMode(LockModeType.PESSIMISTIC_WRITE).getResultList();
}
public List<VirtualIpv6> getVipsByLoadBalancerId(Integer loadBalancerId) {
List<VirtualIpv6> vips;
String query = "select j.virtualIp from LoadBalancerJoinVip6 j where j.loadBalancer.id = :loadBalancerId";
// String query = "select l.virtualIps from LoadBalancer l where l.id = :loadBalancerId";
vips = entityManager.createQuery(query).setParameter("loadBalancerId", loadBalancerId).getResultList();
return vips;
}
public Long getNumIpv6VipsForLoadBalancer(LoadBalancer loadBalancer) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
Root<LoadBalancerJoinVip6> lbJoinVipRoot = criteria.from(LoadBalancerJoinVip6.class);
Expression countExp = builder.count(lbJoinVipRoot.get(LoadBalancerJoinVip6_.virtualIp));
Predicate hasVip = builder.equal(lbJoinVipRoot.get(LoadBalancerJoinVip6_.loadBalancer), loadBalancer);
criteria.select(countExp);
criteria.where(hasVip);
return entityManager.createQuery(criteria).setLockMode(LockModeType.PESSIMISTIC_WRITE).getSingleResult();
}
public Account getLockedAccountRecord(Integer accountId) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Account> criteria = builder.createQuery(Account.class);
Root<Account> accountRoot = criteria.from(Account.class);
Predicate recordWithId = builder.equal(accountRoot.get(Account_.id), accountId);
criteria.select(accountRoot);
criteria.where(recordWithId);
return entityManager.createQuery(criteria).setLockMode(LockModeType.PESSIMISTIC_WRITE).getSingleResult();
}
}