package org.zstack.appliancevm; 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.Platform; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusCallBack; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.SQLBatchWithReturn; import org.zstack.core.db.SimpleQuery; import org.zstack.core.db.SimpleQuery.Op; import org.zstack.core.job.Job; import org.zstack.core.job.JobContext; import org.zstack.header.configuration.InstanceOfferingVO; import org.zstack.header.core.ReturnValueCompletion; import org.zstack.header.image.ImagePlatform; import org.zstack.header.image.ImageVO; import org.zstack.header.image.ImageVO_; import org.zstack.header.message.MessageReply; import org.zstack.header.vm.VmInstanceConstant; import org.zstack.header.vm.VmInstanceSequenceNumberVO; import org.zstack.header.vm.VmInstanceState; import org.zstack.header.vm.VmInstanceVO; import org.zstack.identity.AccountManager; import org.zstack.tag.TagManager; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import java.util.ArrayList; import java.util.List; @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class CreateApplianceVmJob implements Job { protected static final CLogger logger = Utils.getLogger(CreateApplianceVmJob.class); @JobContext protected ApplianceVmSpec spec; @Autowired protected DatabaseFacade dbf; @Autowired protected CloudBus bus; @Autowired private AccountManager acntMgr; @Autowired private ApplianceVmFactory apvmFactory; @Autowired private TagManager tagMgr; @Override public void run(final ReturnValueCompletion<Object> complete) { // if syncCreate is set, the name is the unique id for the vm if (spec.isSyncCreate()) { SimpleQuery<ApplianceVmVO> q = dbf.createQuery(ApplianceVmVO.class); q.add(ApplianceVmVO_.name, SimpleQuery.Op.EQ, spec.getName()); q.add(ApplianceVmVO_.state, SimpleQuery.Op.EQ, VmInstanceState.Running); ApplianceVmVO vo = q.find(); if (vo != null) { complete.success(ApplianceVmInventory.valueOf(vo)); return; } } ApplianceVmVO avo = new ApplianceVmVO(); avo.setName(spec.getName()); if (spec.getUuid() != null) { avo.setUuid(spec.getUuid()); } else { avo.setUuid(Platform.getUuid()); } String defaultRouteL3NetworkUuid = spec.getDefaultRouteL3Network() != null ? spec.getDefaultRouteL3Network().getUuid() : spec.getManagementNic().getL3NetworkUuid(); avo.setDefaultRouteL3NetworkUuid(defaultRouteL3NetworkUuid); avo.setDescription(spec.getDescription()); avo.setImageUuid(spec.getTemplate().getUuid()); avo.setInstanceOfferingUuid(spec.getInstanceOffering().getUuid()); avo.setState(VmInstanceState.Created); avo.setType(ApplianceVmConstant.APPLIANCE_VM_TYPE); avo.setInternalId(dbf.generateSequenceNumber(VmInstanceSequenceNumberVO.class)); avo.setApplianceVmType(spec.getApplianceVmType().toString()); avo.setAgentPort(spec.getAgentPort()); SimpleQuery<ImageVO> imgq = dbf.createQuery(ImageVO.class); imgq.select(ImageVO_.platform); imgq.add(ImageVO_.uuid, Op.EQ, spec.getTemplate().getUuid()); ImagePlatform platform = imgq.findValue(); avo.setPlatform(platform.toString()); InstanceOfferingVO iovo = dbf.findByUuid(spec.getInstanceOffering().getUuid(), InstanceOfferingVO.class); avo.setCpuNum(iovo.getCpuNum()); avo.setCpuSpeed(iovo.getCpuSpeed()); avo.setMemorySize(iovo.getMemorySize()); avo.setAllocatorStrategy(iovo.getAllocatorStrategy()); ApplianceVmSubTypeFactory factory = apvmFactory.getApplianceVmSubTypeFactory(avo.getApplianceVmType()); ApplianceVmVO finalAvo1 = avo; avo = new SQLBatchWithReturn<ApplianceVmVO>() { @Override protected ApplianceVmVO scripts() { ApplianceVmVO vo = factory.persistApplianceVm(spec, finalAvo1); dbf.getEntityManager().flush(); dbf.getEntityManager().refresh(vo); acntMgr.createAccountResourceRef(spec.getAccountUuid(), vo.getUuid(), VmInstanceVO.class); return vo; } }.execute(); tagMgr.copySystemTag(iovo.getUuid(), InstanceOfferingVO.class.getSimpleName(), avo.getUuid(), VmInstanceVO.class.getSimpleName()); if (spec.getInherentSystemTags() != null && !spec.getInherentSystemTags().isEmpty()) { tagMgr.createInherentSystemTags(spec.getInherentSystemTags(), avo.getUuid(), VmInstanceVO.class.getSimpleName()); } if (spec.getNonInherentSystemTags() != null && !spec.getNonInherentSystemTags().isEmpty()) { tagMgr.createNonInherentSystemTags(spec.getNonInherentSystemTags(), avo.getUuid(), VmInstanceVO.class.getSimpleName()); } final ApplianceVmInventory inv = ApplianceVmInventory.valueOf(avo); StartNewCreatedApplianceVmMsg msg = new StartNewCreatedApplianceVmMsg(); List<String> nws = new ArrayList<String>(); nws.add(spec.getManagementNic().getL3NetworkUuid()); for (ApplianceVmNicSpec nicSpec : spec.getAdditionalNics()) { nws.add(nicSpec.getL3NetworkUuid()); } msg.setL3NetworkUuids(nws); msg.setVmInstanceInventory(inv); msg.setApplianceVmSpec(spec); bus.makeTargetServiceIdByResourceUuid(msg, VmInstanceConstant.SERVICE_ID, inv.getUuid()); final ApplianceVmVO finalAvo = avo; bus.send(msg, new CloudBusCallBack(complete) { @Override public void run(MessageReply reply) { if (reply.isSuccess()) { logger.debug(String.format("successfully created appliance vm[uuid:%s, name: %s, appliance vm type: %s]", inv.getUuid(), inv.getName(), inv.getApplianceVmType())); ApplianceVmVO apvo = dbf.findByUuid(finalAvo.getUuid(), ApplianceVmVO.class); ApplianceVmInventory ainv = ApplianceVmInventory.valueOf(apvo); complete.success(ainv); } else { logger.warn(String.format("failed to create appliance vm[uuid:%s, name: %s, appliance vm type: %s], %s", inv.getUuid(), inv.getName(), inv.getApplianceVmType(), reply.getError())); complete.fail(reply.getError()); } } }); } public ApplianceVmSpec getSpec() { return spec; } public void setSpec(ApplianceVmSpec spec) { this.spec = spec; } }