package org.zstack.header.allocator; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Configurable; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.OperationFailureException; import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.host.HostVO; import java.util.ArrayList; import java.util.List; /** */ @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public abstract class AbstractHostAllocatorFlow { protected List<HostVO> candidates; protected HostAllocatorSpec spec; private HostAllocatorTrigger trigger; protected HostAllocationPaginationInfo paginationInfo; public abstract void allocate(); public List<HostVO> getCandidates() { return candidates; } public void setCandidates(List<HostVO> candidates) { this.candidates = candidates; } public HostAllocatorSpec getSpec() { return spec; } public void setSpec(HostAllocatorSpec spec) { this.spec = spec; } public void setTrigger(HostAllocatorTrigger trigger) { this.trigger = trigger; } public HostAllocationPaginationInfo getPaginationInfo() { return paginationInfo; } public void setPaginationInfo(HostAllocationPaginationInfo paginationInfo) { this.paginationInfo = paginationInfo; } protected void next(List<HostVO> candidates) { if (usePagination()) { paginationInfo.setOffset(paginationInfo.getOffset() + paginationInfo.getLimit()); } trigger.next(candidates); } protected void skip() { if (usePagination()) { paginationInfo.setOffset(paginationInfo.getOffset() + paginationInfo.getLimit()); } trigger.skip(); } protected void fail(String reason) { if (paginationInfo != null && trigger.indexOfFlow(this) != 0) { // in pagination, and a middle flow fails, we can continue ErrorCode errorCode = new ErrorCode(); errorCode.setCode(HostAllocatorConstant.PAGINATION_INTERMEDIATE_ERROR.getCode()); errorCode.setDetails(reason); errorCode.setDescription(HostAllocatorConstant.PAGINATION_INTERMEDIATE_ERROR.getDescription()); throw new OperationFailureException(errorCode); } else { // no host found, stop allocating ErrorCode errorCode = new ErrorCode(); errorCode.setCode(HostAllocatorError.NO_AVAILABLE_HOST.toString()); errorCode.setDetails(reason); throw new OperationFailureException(errorCode); } } protected boolean usePagination() { return paginationInfo != null && trigger.indexOfFlow(this) == 0; } protected void throwExceptionIfIAmTheFirstFlow() { if (candidates == null || candidates.isEmpty()) { throw new CloudRuntimeException(String.format("%s cannot be the first flow in the allocation chain", this.getClass().getName())); } } protected List<String> getHostUuidsFromCandidates() { List<String> huuids = new ArrayList<>(candidates.size()); for (HostVO vo : candidates) { huuids.add(vo.getUuid()); } return huuids; } protected boolean amITheFirstFlow() { return candidates == null; } }