package org.zstack.compute.vm; 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.header.core.workflow.Flow; import org.zstack.header.core.workflow.FlowException; import org.zstack.header.core.workflow.FlowRollback; import org.zstack.header.core.workflow.FlowTrigger; import org.zstack.header.core.Completion; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.vm.PreVmInstantiateResourceExtensionPoint; import org.zstack.header.vm.VmInstanceConstant; import org.zstack.header.vm.VmInstanceSpec; import org.zstack.header.vm.VmInstantiateResourceException; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import java.util.Iterator; import java.util.List; import java.util.Map; @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class VmInstantiateResourcePreFlow implements Flow { private static final CLogger logger = Utils.getLogger(VmInstantiateResourcePreFlow.class); @Autowired private PluginRegistry pluginRgty; private static List<PreVmInstantiateResourceExtensionPoint> extensions = null; public VmInstantiateResourcePreFlow() { if (extensions == null) { extensions = pluginRgty.getExtensionList(PreVmInstantiateResourceExtensionPoint.class); } } private void runExtensions(final Iterator<PreVmInstantiateResourceExtensionPoint> it, final VmInstanceSpec spec, final FlowTrigger chain) { if (!it.hasNext()) { chain.next(); return; } PreVmInstantiateResourceExtensionPoint extp = it.next(); logger.debug(String.format("run VmInstantiateResourceExtensionPoint[%s]", extp.getClass())); extp.preInstantiateVmResource(spec, new Completion(chain) { @Override public void success() { runExtensions(it, spec, chain); } @Override public void fail(ErrorCode errorCode) { chain.fail(errorCode); } }); } @Override public void run(FlowTrigger chain, Map data) { VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); for (PreVmInstantiateResourceExtensionPoint extp : extensions) { try { extp.preBeforeInstantiateVmResource(spec); } catch (VmInstantiateResourceException vie) { throw new FlowException(vie.getErrorCode()); } } runExtensions(extensions.iterator(), spec, chain); } private void rollbackExtensions(final Iterator<PreVmInstantiateResourceExtensionPoint> it, final VmInstanceSpec spec, final FlowRollback chain) { if (!it.hasNext()) { chain.rollback(); return; } PreVmInstantiateResourceExtensionPoint extp = it.next(); logger.debug(String.format("rollback VmInstantiateResourceExtensionPoint[%s]", extp.getClass())); extp.preReleaseVmResource(spec, new Completion(chain) { @Override public void success() { rollbackExtensions(it, spec, chain); } @Override public void fail(ErrorCode errorCode) { logger.warn(errorCode.toString()); rollbackExtensions(it, spec, chain); } }); } @Override public void rollback(FlowRollback chain, Map data) { VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); rollbackExtensions(extensions.iterator(), spec, chain); } }