package io.cattle.platform.allocator.constraint; import io.cattle.platform.allocator.exception.FailedToAllocate; import io.cattle.platform.core.dao.GenericMapDao; import io.cattle.platform.core.model.Instance; import io.cattle.platform.core.model.InstanceHostMap; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.inject.Inject; public class CollocationChecker { @Inject GenericMapDao mapDao; /** * Returns a map of host ids to instance ids that should be used to check candidate host ids. The instance ids are provided so that constraints can use them * to provide meaningful output when failing a candidate. * * The map will only ever have a length of 0 or 1. We need to return the host id and instance ids and a map is the most convenient structure for doing so. * Instead of returning a map with a length greater than 1, a FailedToAllocate exception will be raised because that means collocated instances are on * different hosts. * * @param collocatedInstances * @param coscheduledInstances * @return * @throws FailedToAllocate * if a collocated instance is not yet allocated and is not part of the coscheduledInstances or if the collocated instances are not on the same * host already. */ public Map<Long, Set<Long>> checkAndGetCollocatedInstanceHosts(Set<Long> collocatedInstances, Collection<Instance> coscheduledInstances) { for (Instance instance : coscheduledInstances) { collocatedInstances.remove(instance.getId()); } Map<Long, Set<Long>> hostsOfCollocatedInstances = new HashMap<>(); for (Long instanceId : collocatedInstances) { List<? extends InstanceHostMap> maps = mapDao.findNonRemoved(InstanceHostMap.class, Instance.class, instanceId); if (maps.size() > 0) { Long hostId = maps.get(0).getHostId(); if (hostId == null) { throw new FailedToAllocate(String.format("Dependent instance not allocated yet: %s.", instanceId)); } if (!hostsOfCollocatedInstances.containsKey(hostId)) { hostsOfCollocatedInstances.put(hostId, new HashSet<Long>()); } hostsOfCollocatedInstances.get(hostId).add(instanceId); } else { throw new FailedToAllocate(String.format("Dependent instance not allocated yet: %s.", instanceId)); } } if (hostsOfCollocatedInstances.keySet().size() > 1) { throw new FailedToAllocate(String.format( "Dependent instances are allocated to different hosts. Hosts and the dependent instances allocated to them: %s.", hostsOfCollocatedInstances)); } return hostsOfCollocatedInstances; } }