package io.fathom.cloud.compute.services;
import io.fathom.cloud.CloudException;
import io.fathom.cloud.dns.DnsService;
import io.fathom.cloud.dns.DnsService.DnsRecordsetSpec;
import io.fathom.cloud.loadbalancer.LoadBalanceService;
import io.fathom.cloud.openstack.client.loadbalance.model.LbaasMapping;
import io.fathom.cloud.openstack.client.loadbalance.model.LbaasServer;
import io.fathom.cloud.protobuf.CloudModel.InstanceData;
import io.fathom.cloud.server.model.Project;
import java.net.InetAddress;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
import com.google.common.net.InetAddresses;
@Singleton
public class ComputeDerivedMetadataImpl implements ComputeDerivedMetadata {
private static final Logger log = LoggerFactory.getLogger(ComputeDerivedMetadataImpl.class);
public static final String ROLE_LBAAS = "lbaas";
@Inject
DnsService dnsService;
@Inject
LoadBalanceService loadBalanceService;
@Inject
Provider<DerivedMetadata> derivedMetadataProvider;
@Override
public void instanceUpdated(Project project, InstanceData instance) throws CloudException {
DerivedMetadata newMetadata = derivedMetadataProvider.get();
newMetadata.build(instance);
String systemKey = "instance/" + instance.getId() + "/metadata";
List<DnsRecordsetSpec> dnsRecordsets = newMetadata.getDnsRecordsets();
List<LbaasMapping> loadbalanceRecords = newMetadata.getLbaasMappings();
List<String> roles = newMetadata.getRoles();
dnsService.setDnsRecordsets(systemKey, project, dnsRecordsets);
loadBalanceService.setMappings(systemKey, project, loadbalanceRecords);
// We do this so that the LBAAS service can configure DNS
// This is risky though, as the load balancers will then start
// taking traffic, even if they're not fully booted up
// Better might be to have the load balancers register with DNS
// themselves
// (they can do that using the per-instance token)
// Or we could just put a delay in here
// Or we might need another layer (i.e. a layer 4 load balancer in front
// of the layer 7 load balancers)
List<LbaasServer> lbaasServers = Lists.newArrayList();
for (String role : roles) {
if (role.equals(ROLE_LBAAS)) {
List<InetAddress> publicIps = newMetadata.getPublicIps();
if (publicIps.size() == 0) {
log.warn("No public IPs found for load balancer instance: {}", instance);
} else {
if (publicIps.size() != 1) {
log.warn("Multiple public IPs found for load balancer instance, will only use first: {}",
instance);
}
LbaasServer lbaasServer = new LbaasServer();
lbaasServer.ip = InetAddresses.toAddrString(publicIps.get(0));
lbaasServers.add(lbaasServer);
}
} else {
log.info("Ignoring unknown role: " + role);
}
}
loadBalanceService.setServers(systemKey, project, lbaasServers);
}
}