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.allocator.HostAllocatorConstant;
import org.zstack.header.host.HostState;
import org.zstack.header.host.HostStatus;
import org.zstack.header.host.HostVO;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.List;
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class DesignatedHostAllocatorFlow extends AbstractHostAllocatorFlow {
private static final CLogger logger = Utils.getLogger(DesignatedHostAllocatorFlow.class);
@Autowired
private DatabaseFacade dbf;
@Transactional(readOnly = true)
private List<HostVO> allocate(String zoneUuid, String clusterUuid, String hostUuid, String hypervisorType) {
StringBuilder sql = new StringBuilder();
sql.append("select h from HostVO h where ");
if (zoneUuid != null) {
sql.append(String.format("h.zoneUuid = '%s' and ", zoneUuid));
}
if (clusterUuid != null) {
sql.append(String.format("h.clusterUuid = '%s' and ", clusterUuid));
}
if (hostUuid != null) {
sql.append(String.format("h.uuid = '%s' and ", hostUuid));
}
if (hypervisorType != null) {
sql.append(String.format("h.hypervisorType = '%s' and ", hypervisorType));
}
sql.append(String.format("h.status = '%s' and h.state = '%s'", HostStatus.Connected, HostState.Enabled));
TypedQuery<HostVO> query = dbf.getEntityManager().createQuery(sql.toString(), HostVO.class);
if (usePagination()) {
query.setFirstResult(paginationInfo.getOffset());
query.setMaxResults(paginationInfo.getLimit());
}
return query.getResultList();
}
private List<HostVO> allocate(List<HostVO> candidates, String zoneUuid, String clusterUuid, String hostUuid, String hypervisorType) {
List<HostVO> ret = new ArrayList<HostVO>(candidates.size());
for (HostVO h : candidates) {
if (zoneUuid != null && !h.getZoneUuid().equals(zoneUuid)) {
continue;
}
if (clusterUuid != null && !h.getClusterUuid().equals(clusterUuid)) {
continue;
}
if (hostUuid != null && !h.getUuid().equals(hostUuid)) {
continue;
}
if (hypervisorType != null && !h.getHypervisorType().equals(hypervisorType)) {
continue;
}
ret.add(h);
}
return ret;
}
@Override
public void allocate() {
String zoneUuid = (String) spec.getExtraData().get(HostAllocatorConstant.LocationSelector.zone);
String clusterUuid = (String) spec.getExtraData().get(HostAllocatorConstant.LocationSelector.cluster);
String hostUuid = (String) spec.getExtraData().get(HostAllocatorConstant.LocationSelector.host);
if (zoneUuid == null && clusterUuid == null && hostUuid == null && spec.getHypervisorType() == null) {
next(candidates);
return;
}
if (amITheFirstFlow()) {
candidates = allocate(zoneUuid, clusterUuid, hostUuid, spec.getHypervisorType());
} else {
candidates = allocate(candidates, zoneUuid, clusterUuid, hostUuid, spec.getHypervisorType());
}
if (candidates.isEmpty()) {
StringBuilder err = new StringBuilder("No host with ");
if (zoneUuid != null) {
err.append(String.format("zoneUuid=%s ", zoneUuid));
}
if (clusterUuid != null) {
err.append(String.format("clusterUuid=%s ", clusterUuid));
}
if (hostUuid != null) {
err.append(String.format("uuid=%s ", hostUuid));
}
if (spec.getHypervisorType() != null) {
err.append(String.format("hypervisorType=%s ", spec.getHypervisorType()));
}
err.append("found");
fail(err.toString());
} else {
next(candidates);
}
}
}