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.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.errorcode.OperationFailureException;
import org.zstack.header.allocator.*;
import org.zstack.header.configuration.DiskOfferingInventory;
import org.zstack.header.configuration.DiskOfferingVO;
import org.zstack.header.configuration.InstanceOfferingVO;
import org.zstack.header.host.HostVO;
import org.zstack.header.tag.SystemTagInventory;
import org.zstack.header.tag.SystemTagVO;
import org.zstack.header.tag.SystemTagVO_;
import org.zstack.header.vm.VmInstance;
import org.zstack.header.vm.VmInstanceVO;
import org.zstack.utils.CollectionUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.function.Function;
import org.zstack.utils.logging.CLogger;
import java.util.List;
/**
*/
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
public class TagAllocatorFlow extends AbstractHostAllocatorFlow {
private static final CLogger logger = Utils.getLogger(TagAllocatorFlow.class);
@Autowired
private DatabaseFacade dbf;
@Autowired
private PluginRegistry pluginRgty;
private List<InstanceOfferingTagAllocatorExtensionPoint> instanceOfferingExtensions;
private List<DiskOfferingTagAllocatorExtensionPoint> diskOfferingExtensions;
public TagAllocatorFlow() {
instanceOfferingExtensions = pluginRgty.getExtensionList(InstanceOfferingTagAllocatorExtensionPoint.class);
diskOfferingExtensions = pluginRgty.getExtensionList(DiskOfferingTagAllocatorExtensionPoint.class);
}
@Override
public void allocate() {
throwExceptionIfIAmTheFirstFlow();
if (!instanceOfferingExtensions.isEmpty()) {
SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
q.add(SystemTagVO_.resourceType, Op.EQ, VmInstanceVO.class.getSimpleName());
q.add(SystemTagVO_.resourceUuid, Op.EQ, spec.getVmInstance().getUuid());
List<SystemTagVO> tvos = q.list();
if (!tvos.isEmpty()) {
List tinvs = SystemTagInventory.valueOf(tvos);
List<HostVO> tmp = candidates;
for (InstanceOfferingTagAllocatorExtensionPoint extp : instanceOfferingExtensions) {
List<HostVO> ret = extp.allocateHost(tinvs, tmp, spec);
if (ret == null) {
continue;
}
tmp = ret;
if (tmp.isEmpty()) {
fail(String.format("InstanceOfferingTagAllocatorExtensionPoint[%s] return zero candidate host", extp.getClass().getName()));
return;
} else {
logger.debug(String.format("[Host Allocation]: InstanceOfferingTagAllocatorExtensionPoint[%s] successfully found %s candidate hosts for vm[uuid:%s, name:%s]",
extp.getClass().getName(), tmp.size(), spec.getVmInstance().getUuid(), spec.getVmInstance().getName()));
}
}
candidates = tmp;
}
}
if (!diskOfferingExtensions.isEmpty() && spec.getDiskOfferings() != null && !spec.getDiskOfferings().isEmpty()) {
List<String> diskOfferingUuids = CollectionUtils.transformToList(spec.getDiskOfferings(), new Function<String, DiskOfferingInventory>() {
@Override
public String call(DiskOfferingInventory arg) {
return arg.getUuid();
}
});
SimpleQuery<SystemTagVO> q = dbf.createQuery(SystemTagVO.class);
q.add(SystemTagVO_.resourceType, Op.EQ, DiskOfferingVO.class.getSimpleName());
q.add(SystemTagVO_.resourceUuid, Op.IN, diskOfferingUuids);
List<SystemTagVO> tvos = q.list();
if (!tvos.isEmpty()) {
List tinvs = SystemTagInventory.valueOf(tvos);
List<HostVO> tmp = candidates;
for (DiskOfferingTagAllocatorExtensionPoint extp : diskOfferingExtensions) {
List<HostVO> ret = extp.allocateHost(tinvs, tmp, spec);
if (ret == null) {
continue;
}
tmp = ret;
if (tmp.isEmpty()) {
fail(String.format("DiskOfferingTagAllocatorExtensionPoint[%s] return zero candidate host", extp.getClass().getName()));
return;
} else {
logger.debug(String.format("[Host Allocation]: DiskOfferingTagAllocatorExtensionPoint[%s] successfully found %s candidate hosts for vm[uuid:%s, name:%s]",
extp.getClass().getName(), tmp.size(), spec.getVmInstance().getUuid(), spec.getVmInstance().getName()));
}
}
candidates = tmp;
}
}
next(candidates);
}
}