package org.zstack.storage.primary; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.zstack.header.core.workflow.FlowChain; import org.zstack.core.workflow.FlowChainBuilder; import org.zstack.header.core.workflow.FlowDoneHandler; import org.zstack.header.core.workflow.FlowErrorHandler; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.OperationFailureException; import org.zstack.header.storage.primary.*; import org.zstack.header.storage.primary.PrimaryStorageConstant.AllocatorParams; import java.util.Collections; import java.util.List; import java.util.Map; import static org.zstack.utils.CollectionDSL.e; import static org.zstack.utils.CollectionDSL.map; @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) class DefaultPrimaryStorageAllocatorStrategy implements PrimaryStorageAllocatorStrategy { private FlowChainBuilder builder; @Autowired private DiskCapacityTracer tracker; DefaultPrimaryStorageAllocatorStrategy(FlowChainBuilder builder) { this.builder = builder; } @Override public PrimaryStorageInventory allocate(PrimaryStorageAllocationSpec spec) { return allocateAllCandidates(spec).get(0); } @Override public List<PrimaryStorageInventory> allocateAllCandidates(PrimaryStorageAllocationSpec spec) { List<PrimaryStorageVO> candidates = allocateAll(spec); Collections.shuffle(candidates); return PrimaryStorageInventory.valueOf(candidates); } private List<PrimaryStorageVO> allocateAll(PrimaryStorageAllocationSpec spec) { class Result { List<PrimaryStorageVO> result; ErrorCode errorCode; } final Result ret = new Result(); FlowChain allocatorChain = builder.build(); allocatorChain.setName(String.format("allocate-primary-storage-msg-%s", spec.getAllocationMessage().getId())); allocatorChain.setData(map(e(AllocatorParams.SPEC, spec))); allocatorChain.done(new FlowDoneHandler(null) { @Override public void handle(Map data) { ret.result = (List<PrimaryStorageVO>) data.get(AllocatorParams.CANDIDATES); } }).error(new FlowErrorHandler(null) { @Override public void handle(ErrorCode errCode, Map data) { ret.errorCode = errCode; } }); tracker.trackAllocatorChain(allocatorChain); allocatorChain.start(); if (ret.errorCode != null) { throw new OperationFailureException(ret.errorCode); } else { return ret.result; } } }