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.core.componentloader.PluginRegistry;
import org.zstack.core.db.DatabaseFacade;
import org.zstack.core.db.SimpleQuery;
import org.zstack.core.db.SimpleQuery.Op;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.core.workflow.NoRollbackFlow;
import org.zstack.header.configuration.DiskOfferingVO;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.storage.primary.PrimaryStorageAllocationSpec;
import org.zstack.header.storage.primary.PrimaryStorageConstant.AllocatorParams;
import org.zstack.header.storage.primary.PrimaryStorageTagAllocatorExtensionPoint;
import org.zstack.header.storage.primary.PrimaryStorageVO;
import org.zstack.header.tag.SystemTagInventory;
import org.zstack.header.tag.SystemTagVO;
import org.zstack.header.tag.SystemTagVO_;
import org.zstack.header.vm.VmInstanceVO;
import org.zstack.utils.DebugUtils;
import static org.zstack.core.Platform.operr;
import java.util.List;
import java.util.Map;
/**
*/
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class PrimaryStorageTagAllocatorFlow extends NoRollbackFlow {
@Autowired
protected DatabaseFacade dbf;
@Autowired
protected ErrorFacade errf;
@Autowired
private PluginRegistry pluginRgty;
protected static List<PrimaryStorageTagAllocatorExtensionPoint> tagExtensions;
public PrimaryStorageTagAllocatorFlow() {
if (tagExtensions == null) {
tagExtensions = pluginRgty.getExtensionList(PrimaryStorageTagAllocatorExtensionPoint.class);
}
}
@Override
public void run(FlowTrigger trigger, Map data) {
PrimaryStorageAllocationSpec spec = (PrimaryStorageAllocationSpec) data.get(AllocatorParams.SPEC);
List<PrimaryStorageVO> candidates = (List<PrimaryStorageVO>) data.get(AllocatorParams.CANDIDATES);
DebugUtils.Assert(candidates != null && !candidates.isEmpty(), "PrimaryStorageTagAllocatorFlow cannot be the first element in allocator chain");
List<SystemTagVO> tvos = null;
if (spec.getVmInstanceUuid() != null) {
SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
q.add(SystemTagVO_.resourceType, Op.EQ, VmInstanceVO.class.getSimpleName());
q.add(SystemTagVO_.resourceUuid, Op.EQ, spec.getVmInstanceUuid());
tvos = q.list();
} else if (spec.getDiskOfferingUuid() != null) {
SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
q.add(SystemTagVO_.resourceType, Op.EQ, DiskOfferingVO.class.getSimpleName());
q.add(SystemTagVO_.resourceUuid, Op.EQ, spec.getDiskOfferingUuid());
tvos = q.list();
}
if (tvos != null && !tvos.isEmpty()) {
candidates = callTagExtensions(SystemTagInventory.valueOf(tvos), candidates);
data.put(AllocatorParams.CANDIDATES, candidates);
}
trigger.next();
}
protected List<PrimaryStorageVO> callTagExtensions(List<SystemTagInventory> tags, List<PrimaryStorageVO> candidates) {
List<PrimaryStorageVO> ret = null;
for (PrimaryStorageTagAllocatorExtensionPoint extp : tagExtensions) {
ret = extp.allocatePrimaryStorage(tags, candidates);
if (ret == null) {
continue;
}
if (ret.isEmpty()) {
throw new OperationFailureException(operr("PrimaryStorageTagAllocatorExtensionPoint[%s] returns zero primary storage candidate", extp.getClass().getName()));
}
candidates = ret;
}
return candidates;
}
}