package org.zstack.compute.allocator; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.transaction.annotation.Transactional; import org.zstack.core.db.DatabaseFacade; import org.zstack.header.allocator.AbstractHostAllocatorFlow; import org.zstack.header.host.HostState; import org.zstack.header.host.HostStatus; import org.zstack.header.host.HostVO; import org.zstack.header.vm.VmInstanceInventory; import org.zstack.header.volume.VolumeInventory; import org.zstack.utils.CollectionUtils; import org.zstack.utils.Utils; import org.zstack.utils.function.Function; import org.zstack.utils.logging.CLogger; import javax.persistence.TypedQuery; import java.util.List; import java.util.Set; @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class AttachedPrimaryStorageAllocatorFlow extends AbstractHostAllocatorFlow { private static final CLogger logger = Utils.getLogger(AttachedPrimaryStorageAllocatorFlow.class); @Autowired private DatabaseFacade dbf; @Transactional(readOnly = true) private List<HostVO> allocate(Set<String> psUuids, VmInstanceInventory vm) { if (getCandidates() != null) { String sql = "select h from HostVO h where h.clusterUuid in (select pcr.clusterUuid from PrimaryStorageClusterRefVO pcr where pcr.primaryStorageUuid in :psUuids group by pcr.clusterUuid having count(pcr.clusterUuid) = :psUuidSize) and h.state = :hostState and h.status = :hostConnectionState and h.hypervisorType = :hypervisorType and h.uuid in :hostUuids"; TypedQuery<HostVO> query = dbf.getEntityManager().createQuery(sql, HostVO.class); query.setParameter("psUuids", psUuids); query.setParameter("psUuidSize", psUuids.size()); query.setParameter("hostState", HostState.Enabled); query.setParameter("hostConnectionState", HostStatus.Connected); query.setParameter("hypervisorType", vm.getHypervisorType()); query.setParameter("hostUuids", getHostUuidsFromCandidates()); if (usePagination()) { query.setFirstResult(paginationInfo.getOffset()); query.setMaxResults(paginationInfo.getLimit()); } return query.getResultList(); } else { String sql = "select h from HostVO h where h.clusterUuid in (select pcr.clusterUuid from PrimaryStorageClusterRefVO pcr where pcr.primaryStorageUuid in :psUuids group by pcr.clusterUuid having count(pcr.clusterUuid) = :psUuidSize) and h.state = :hostState and h.status = :hostConnectionState and h.hypervisorType = :hypervisorType"; TypedQuery<HostVO> query = dbf.getEntityManager().createQuery(sql, HostVO.class); query.setParameter("psUuids", psUuids); query.setParameter("psUuidSize", Long.valueOf(psUuids.size())); query.setParameter("hostState", HostState.Enabled); query.setParameter("hostConnectionState", HostStatus.Connected); query.setParameter("hypervisorType", vm.getHypervisorType()); if (usePagination()) { query.setFirstResult(paginationInfo.getOffset()); query.setMaxResults(paginationInfo.getLimit()); } return query.getResultList(); } } @Override public void allocate() { VmInstanceInventory vm = spec.getVmInstance(); Set<String> psuuids = CollectionUtils.transformToSet(vm.getAllVolumes(), new Function<String, VolumeInventory>() { @Override public String call(VolumeInventory arg) { return arg.getPrimaryStorageUuid(); } }); candidates = allocate(psuuids, vm); if (candidates.isEmpty()) { fail(String.format("no host found in clusters that have attached to primary storage%s", psuuids)); } else { next(candidates); } } }