Esempio n. 1
0
  @Test
  public void test() throws ApiSenderException {
    VmInstanceInventory vm = deployer.vms.get("TestVm");
    api.stopVmInstance(vm.getUuid());
    PrimaryStorageInventory local = deployer.primaryStorages.get("local");

    VolumeSnapshotInventory sp = api.createSnapshot(vm.getRootVolumeUuid());
    Assert.assertFalse(kconfig.snapshotCmds.isEmpty());
    LocalStorageResourceRefVO ref = dbf.findByUuid(sp.getUuid(), LocalStorageResourceRefVO.class);
    Assert.assertNotNull(ref);
    Assert.assertEquals(vm.getHostUuid(), ref.getHostUuid());

    sp = api.createSnapshot(vm.getRootVolumeUuid());
    ref = dbf.findByUuid(sp.getUuid(), LocalStorageResourceRefVO.class);
    Assert.assertNotNull(ref);
    Assert.assertEquals(vm.getHostUuid(), ref.getHostUuid());

    sp = api.createSnapshot(vm.getRootVolumeUuid());
    ref = dbf.findByUuid(sp.getUuid(), LocalStorageResourceRefVO.class);
    Assert.assertNotNull(ref);
    Assert.assertEquals(vm.getHostUuid(), ref.getHostUuid());

    PrimaryStorageVO localvo = dbf.findByUuid(local.getUuid(), PrimaryStorageVO.class);
    long avail = localvo.getCapacity().getAvailableCapacity();

    ImageInventory img = api.createTemplateFromSnapshot(sp.getUuid());
    Assert.assertTrue(img.getSize() != 0);

    localvo = dbf.findByUuid(local.getUuid(), PrimaryStorageVO.class);
    Assert.assertEquals(avail, localvo.getCapacity().getAvailableCapacity());
  }
Esempio n. 2
0
  @Test
  public void test() throws ApiSenderException, InterruptedException {
    ImageInventory img = deployer.images.get("TestImage");
    VmInstanceInventory vm = deployer.vms.get("TestVm");

    api.deleteImage(img.getUuid());

    api.stopVmInstance(vm.getUuid());
    api.startVmInstance(vm.getUuid());
    api.rebootVmInstance(vm.getUuid());
    api.destroyVmInstance(vm.getUuid());
  }
Esempio n. 3
0
  @Test
  public void test() throws ApiSenderException, InterruptedException {
    CoreGlobalProperty.VM_TRACER_ON = false;
    IdentityGlobalConfig.SESSION_TIMEOUT.updateValue(TimeUnit.HOURS.toSeconds(1000));
    api.prepare();
    InstanceOfferingInventory ioinv = api.listInstanceOffering(null).get(0);
    ImageInventory iminv = api.listImage(null).get(0);
    List<DiskOfferingInventory> dinvs = api.listDiskOffering(null);
    List<L3NetworkInventory> nwinvs = api.listL3Network(null);
    List<String> nws = new ArrayList<String>(nwinvs.size());
    for (L3NetworkInventory nwinv : nwinvs) {
      nws.add(nwinv.getUuid());
    }

    for (int i = 0; i < vmNum; i++) {
      VmInstanceInventory vm = new VmInstanceInventory();
      vm.setDescription("TestVm");
      vm.setName("TestVm");
      vm.setType(VmInstanceConstant.USER_VM_TYPE);
      vm.setInstanceOfferingUuid(ioinv.getUuid());
      vm.setImageUuid(iminv.getUuid());
      createVm(vm, dinvs.get(0).getUuid(), nws, new ArrayList<String>());
    }
    latch.await(600, TimeUnit.MINUTES);
    long totalTime = 0;
    long minTime = 0;
    long maxTime = 0;
    for (Long t : timeCost) {
      minTime = Math.min(minTime, t);
      maxTime = Math.max(maxTime, t);
      totalTime += t;
    }
    System.out.println(
        String.format(
            "total time: %s, min time: %s, max time: %s, avg  time: %s",
            TimeUnit.MILLISECONDS.toSeconds(totalTime),
            TimeUnit.MILLISECONDS.toSeconds(minTime),
            TimeUnit.MILLISECONDS.toSeconds(maxTime),
            TimeUnit.MILLISECONDS.toSeconds(totalTime / timeCost.size())));

    /*
    SimpleQuery<VmInstanceVO> q = dbf.createQuery(VmInstanceVO.class);
    q.add(VmInstanceVO_.state, Op.EQ, VmInstanceState.Running);
    long count = q.count();
    Assert.assertEquals(vmNum, count);
    */
    TimeUnit.HOURS.sleep(1000);
  }
Esempio n. 4
0
  private void handle(final CreateDataVolumeTemplateFromDataVolumeMsg msg) {
    final CreateTemplateFromVolumeOnPrimaryStorageMsg cmsg =
        new CreateTemplateFromVolumeOnPrimaryStorageMsg();
    cmsg.setBackupStorageUuid(msg.getBackupStorageUuid());
    cmsg.setImageInventory(
        ImageInventory.valueOf(dbf.findByUuid(msg.getImageUuid(), ImageVO.class)));
    cmsg.setVolumeInventory(getSelfInventory());
    bus.makeTargetServiceIdByResourceUuid(
        cmsg, PrimaryStorageConstant.SERVICE_ID, self.getPrimaryStorageUuid());
    bus.send(
        cmsg,
        new CloudBusCallBack(msg) {
          @Override
          public void run(MessageReply r) {
            CreateDataVolumeTemplateFromDataVolumeReply reply =
                new CreateDataVolumeTemplateFromDataVolumeReply();
            if (!r.isSuccess()) {
              reply.setError(r.getError());
            } else {
              CreateTemplateFromVolumeOnPrimaryStorageReply creply = r.castReply();
              String backupStorageInstallPath = creply.getTemplateBackupStorageInstallPath();
              reply.setFormat(creply.getFormat());
              reply.setInstallPath(backupStorageInstallPath);
              reply.setMd5sum(null);
              reply.setBackupStorageUuid(msg.getBackupStorageUuid());
            }

            bus.reply(msg, reply);
          }
        });
  }
 @Test
 public void test() throws ApiSenderException {
   ImageInventory iminv = deployer.images.get("TestImage");
   InstanceOfferingInventory ioinv = deployer.instanceOfferings.get("TestInstanceOffering");
   L3NetworkInventory l3inv = deployer.l3Networks.get("TestL3Network2");
   APICreateVmInstanceMsg msg = new APICreateVmInstanceMsg();
   msg.setImageUuid(iminv.getUuid());
   msg.setInstanceOfferingUuid(ioinv.getUuid());
   List<String> l3uuids = new ArrayList<String>();
   l3uuids.add(l3inv.getUuid());
   msg.setL3NetworkUuids(l3uuids);
   msg.setName("TestVm");
   msg.setSession(session);
   msg.setServiceId(ApiMediatorConstant.SERVICE_ID);
   msg.setType(VmInstanceConstant.USER_VM_TYPE);
   ApiSender sender = api.getApiSender();
   sender.send(msg, APICreateVmInstanceEvent.class);
 }
  @Test
  public void test() throws ApiSenderException {
    L3NetworkInventory l3 = deployer.l3Networks.get("l3Network1");
    InstanceOfferingInventory instanceOffering =
        deployer.instanceOfferings.get("instanceOffering512M512HZ");
    ImageInventory imageInventory = deployer.images.get("image1");
    ZoneInventory zone1 = deployer.zones.get("zone1");

    VmCreator creator = new VmCreator();
    creator.addL3Network(l3.getUuid());
    creator.imageUuid = imageInventory.getUuid();
    creator.instanceOfferingUuid = instanceOffering.getUuid();
    creator.zoneUuid = zone1.getUuid();
    VmInstanceInventory vm = creator.create();
    HostCapacityVO cvo = dbf.findByUuid(vm.getHostUuid(), HostCapacityVO.class);
    Assert.assertEquals(instanceOffering.getCpuNum(), cvo.getUsedCpu());
    Assert.assertEquals(instanceOffering.getMemorySize(), cvo.getUsedMemory());
    Assert.assertEquals(zone1.getUuid(), vm.getZoneUuid());
  }
Esempio n. 7
0
  @Test
  public void test() throws ApiSenderException {
    VmInstanceInventory vm = deployer.vms.get("TestVm");
    ImageInventory iso = deployer.images.get("TestIso");
    PrimaryStorageInventory ps = deployer.primaryStorages.get("ceph-pri");

    restf.installBeforeAsyncJsonPostInterceptor(
        new BeforeAsyncJsonPostInterceptor() {
          @Override
          public void beforeAsyncJsonPost(String url, Object body, TimeUnit unit, long timeout) {
            if (body instanceof AttachIsoCmd) {
              AttachIsoCmd cmd = (AttachIsoCmd) body;
              isoto = (KvmCephIsoTO) cmd.iso;
            }
          }

          @Override
          public void beforeAsyncJsonPost(String url, String body, TimeUnit unit, long timeout) {}
        });

    api.attachIso(vm.getUuid(), iso.getUuid(), null);
    Assert.assertNotNull(isoto);
    Assert.assertFalse(isoto.getMonInfo().isEmpty());

    CephPrimaryStorageVO ceph = dbf.findByUuid(ps.getUuid(), CephPrimaryStorageVO.class);
    Assert.assertEquals(ceph.getMons().size(), isoto.getMonInfo().size());

    for (final CephPrimaryStorageMonVO mon : ceph.getMons()) {
      MonInfo info =
          CollectionUtils.find(
              isoto.getMonInfo(),
              new Function<MonInfo, MonInfo>() {
                @Override
                public MonInfo call(MonInfo arg) {
                  return arg.getHostname().equals(mon.getHostname()) ? arg : null;
                }
              });

      Assert.assertNotNull(info);
    }
  }
Esempio n. 8
0
  @Test
  public void test() throws ApiSenderException, InterruptedException {
    final BackupStorageInventory sftp = deployer.backupStorages.get("sftp");
    final ImageInventory img = new ImageInventory();
    img.setName("image");
    img.setPlatform(ImagePlatform.Linux.toString());
    img.setMediaType(ImageMediaType.RootVolumeTemplate.toString());
    img.setFormat("qcow2");
    img.setUrl("http://test.img");

    for (int i = 0; i < num; i++) {
      createVm(img, sftp.getUuid());
    }

    latch.await(5, TimeUnit.MINUTES);

    Assert.assertEquals(num, vms.size());

    fconfig.applyDhcpCmdList.clear();
    HostInventory host = deployer.hosts.get("host1");
    api.reconnectHost(host.getUuid());
    Assert.assertFalse(fconfig.applyDhcpCmdList.isEmpty());
    ApplyDhcpCmd cmd = fconfig.applyDhcpCmdList.get(0);
    Assert.assertEquals(num + 1, cmd.dhcp.size());

    List<VmInstanceVO> vms = dbf.listAll(VmInstanceVO.class);
    for (VmInstanceVO vm : vms) {
      checkNic(vm, cmd.dhcp);
    }
  }
Esempio n. 9
0
  private void handle(APIChangeImageStateMsg msg) {
    ImageStateEvent sevt = ImageStateEvent.valueOf(msg.getStateEvent());
    if (sevt == ImageStateEvent.disable) {
      self.setState(ImageState.Disabled);
    } else {
      self.setState(ImageState.Enabled);
    }
    self = dbf.updateAndRefresh(self);

    APIChangeImageStateEvent evt = new APIChangeImageStateEvent(msg.getId());
    evt.setInventory(ImageInventory.valueOf(self));
    bus.publish(evt);
  }
Esempio n. 10
0
 @AsyncThread
 private void createVm(ImageInventory img, String bsUuid) throws ApiSenderException {
   img = api.addImage(img, bsUuid);
   InstanceOfferingInventory ioinv = deployer.instanceOfferings.get("small");
   L3NetworkInventory l3 = deployer.l3Networks.get("TestL3Network1");
   VmCreator creator = new VmCreator(api);
   creator.imageUuid = img.getUuid();
   creator.session = api.getAdminSession();
   creator.instanceOfferingUuid = ioinv.getUuid();
   creator.name = "vm";
   creator.addL3Network(l3.getUuid());
   try {
     synchronized (vms) {
       vms.add(creator.create());
     }
   } finally {
     latch.countDown();
   }
 }
  @Test
  public void test() throws ApiSenderException {
    VmInstanceInventory vm = deployer.vms.get("TestVm");
    api.stopVmInstance(vm.getUuid());
    String rootVolumeUuid = vm.getRootVolumeUuid();
    VolumeVO vol = dbf.findByUuid(rootVolumeUuid, VolumeVO.class);

    BackupStorageInventory sftp = deployer.backupStorages.get("sftp");
    ImageInventory image =
        api.createTemplateFromRootVolume("testImage", rootVolumeUuid, (List) null);
    Assert.assertEquals(sftp.getUuid(), image.getBackupStorageRefs().get(0).getBackupStorageUuid());
    Assert.assertEquals(ImageStatus.Ready.toString(), image.getStatus());
    Assert.assertEquals(vol.getSize(), image.getSize());
    Assert.assertEquals(String.format("volume://%s", vol.getUuid()), image.getUrl());

    ImageVO ivo = dbf.findByUuid(image.getUuid(), ImageVO.class);
    Assert.assertNotNull(ivo);
  }
Esempio n. 12
0
 protected ImageInventory getSelfInventory() {
   return ImageInventory.valueOf(getSelf());
 }
Esempio n. 13
0
  private void handle(APIDeleteImageMsg msg) {
    final APIDeleteImageEvent evt = new APIDeleteImageEvent(msg.getId());

    final String issuer = ImageVO.class.getSimpleName();
    ImageDeletionStruct struct = new ImageDeletionStruct();
    struct.setImage(ImageInventory.valueOf(self));
    struct.setBackupStorageUuids(msg.getBackupStorageUuids());
    final List<ImageDeletionStruct> ctx = Arrays.asList(struct);
    FlowChain chain = FlowChainBuilder.newSimpleFlowChain();
    chain.setName(String.format("delete-image-%s", msg.getUuid()));
    if (msg.getDeletionMode() == APIDeleteMessage.DeletionMode.Permissive) {
      chain
          .then(
              new NoRollbackFlow() {
                @Override
                public void run(final FlowTrigger trigger, Map data) {
                  casf.asyncCascade(
                      CascadeConstant.DELETION_CHECK_CODE,
                      issuer,
                      ctx,
                      new Completion(trigger) {
                        @Override
                        public void success() {
                          trigger.next();
                        }

                        @Override
                        public void fail(ErrorCode errorCode) {
                          trigger.fail(errorCode);
                        }
                      });
                }
              })
          .then(
              new NoRollbackFlow() {
                @Override
                public void run(final FlowTrigger trigger, Map data) {
                  casf.asyncCascade(
                      CascadeConstant.DELETION_DELETE_CODE,
                      issuer,
                      ctx,
                      new Completion(trigger) {
                        @Override
                        public void success() {
                          trigger.next();
                        }

                        @Override
                        public void fail(ErrorCode errorCode) {
                          trigger.fail(errorCode);
                        }
                      });
                }
              });
    } else {
      chain.then(
          new NoRollbackFlow() {
            @Override
            public void run(final FlowTrigger trigger, Map data) {
              casf.asyncCascade(
                  CascadeConstant.DELETION_FORCE_DELETE_CODE,
                  issuer,
                  ctx,
                  new Completion(trigger) {
                    @Override
                    public void success() {
                      trigger.next();
                    }

                    @Override
                    public void fail(ErrorCode errorCode) {
                      trigger.fail(errorCode);
                    }
                  });
            }
          });
    }

    chain
        .done(
            new FlowDoneHandler(msg) {
              @Override
              public void handle(Map data) {
                casf.asyncCascadeFull(
                    CascadeConstant.DELETION_CLEANUP_CODE, issuer, ctx, new NopeCompletion());
                bus.publish(evt);
              }
            })
        .error(
            new FlowErrorHandler(msg) {
              @Override
              public void handle(ErrorCode errCode, Map data) {
                evt.setErrorCode(
                    errf.instantiateErrorCode(SysErrors.DELETE_RESOURCE_ERROR, errCode));
                bus.publish(evt);
              }
            })
        .start();
  }
  @Test
  public void test() throws ApiSenderException, InterruptedException {
    InstanceOfferingInventory ioinv = deployer.instanceOfferings.get("TestInstanceOffering");
    ImageInventory img = deployer.images.get("TestImage");
    L3NetworkInventory l3 = deployer.l3Networks.get("TestL3Network1");
    DiskOfferingInventory disk = deployer.diskOfferings.get("disk50G");

    IdentityCreator identityCreator = new IdentityCreator(api);
    AccountInventory test = identityCreator.useAccount("test");

    // some image set in xml,some below,the amount should one more than the quota to get expected
    // exceeding exception.
    api.updateQuota(test.getUuid(), ImageConstant.QUOTA_IMAGE_NUM, 4);

    BackupStorageInventory bsInv = deployer.backupStorages.get("TestImageStoreBackupStorage");

    // add image by http
    ImageInventory iinv = new ImageInventory();
    iinv.setUuid(Platform.getUuid());
    iinv.setName("Test Image1");
    iinv.setDescription("Test Image1");
    iinv.setMediaType(ImageConstant.ImageMediaType.RootVolumeTemplate.toString());
    iinv.setGuestOsType("Window7");
    iinv.setFormat("simulator");
    iinv.setUrl("http://192.168.200.1/mirror/diskimages/centos6-test.qcow2");
    iinv = api.addImage(iinv, identityCreator.getAccountSession(), bsInv.getUuid());

    // add image by local file
    iinv = new ImageInventory();
    iinv.setUuid(Platform.getUuid());
    iinv.setName("Test Image1");
    iinv.setDescription("Test Image1");
    iinv.setMediaType(ImageConstant.ImageMediaType.RootVolumeTemplate.toString());
    iinv.setGuestOsType("Window7");
    iinv.setFormat("simulator");
    iinv.setUrl("file://///home/miao/Desktop/zstack2/imageStore1.zip");
    // for getImageSize response
    iConfig.getImageSizeCmdSize.put(iinv.getUuid(), SizeUnit.GIGABYTE.toByte(2));
    // for download response
    iConfig.imageSizes.put(iinv.getUuid(), SizeUnit.GIGABYTE.toByte(1));
    iinv = api.addImage(iinv, identityCreator.getAccountSession(), bsInv.getUuid());

    // add image by local file
    iinv = new ImageInventory();
    iinv.setUuid(Platform.getUuid());
    iinv.setName("Test Image1");
    iinv.setDescription("Test Image1");
    iinv.setMediaType(ImageConstant.ImageMediaType.RootVolumeTemplate.toString());
    iinv.setGuestOsType("Window7");
    iinv.setFormat("simulator");
    iinv.setUrl("file://///home/miao/Desktop/zstack2/imageStore2.zip");
    iConfig.getImageSizeCmdSize.put(iinv.getUuid(), SizeUnit.GIGABYTE.toByte(2));
    iinv = api.addImage(iinv, identityCreator.getAccountSession(), bsInv.getUuid());

    // add image by http to exceed quota:image.num
    iinv = new ImageInventory();
    iinv.setUuid(Platform.getUuid());
    iinv.setName("Test Image2");
    iinv.setDescription("Test Image2");
    iinv.setMediaType(ImageConstant.ImageMediaType.RootVolumeTemplate.toString());
    iinv.setGuestOsType("Window7");
    iinv.setFormat("simulator");
    iinv.setUrl("http://192.168.200.1/mirror/diskimages/exceed.img");

    thrown.expect(ApiSenderException.class);
    thrown.expectMessage("The user exceeds a quota of a resource");
    thrown.expectMessage(ImageConstant.QUOTA_IMAGE_NUM);

    iConfig.getImageSizeCmdSize.put(iinv.getUuid(), SizeUnit.MEGABYTE.toByte(233));
    iinv = api.addImage(iinv, identityCreator.getAccountSession(), bsInv.getUuid());
    //
    List<Quota.QuotaUsage> usages = api.getQuotaUsage(test.getUuid(), null);
    //
    Quota.QuotaUsage imageNum =
        CollectionUtils.find(
            usages,
            new Function<Quota.QuotaUsage, Quota.QuotaUsage>() {
              @Override
              public Quota.QuotaUsage call(Quota.QuotaUsage arg) {
                return ImageConstant.QUOTA_IMAGE_NUM.equals(arg.getName()) ? arg : null;
              }
            });
    Assert.assertNotNull(imageNum);
    QuotaInventory qvm =
        api.getQuota(
            ImageConstant.QUOTA_IMAGE_NUM, test.getUuid(), identityCreator.getAccountSession());
    Assert.assertEquals(qvm.getValue(), imageNum.getTotal().longValue());
    Assert.assertEquals(2, imageNum.getUsed().longValue());
    //
    Quota.QuotaUsage imageSize =
        CollectionUtils.find(
            usages,
            new Function<Quota.QuotaUsage, Quota.QuotaUsage>() {
              @Override
              public Quota.QuotaUsage call(Quota.QuotaUsage arg) {
                return ImageConstant.QUOTA_IMAGE_SIZE.equals(arg.getName()) ? arg : null;
              }
            });
    Assert.assertNotNull(imageSize);
    qvm =
        api.getQuota(
            ImageConstant.QUOTA_IMAGE_SIZE, test.getUuid(), identityCreator.getAccountSession());
    Assert.assertEquals(qvm.getValue(), imageSize.getTotal().longValue());
    Assert.assertTrue(imageSize.getUsed().longValue() <= imageSize.getTotal().longValue());
  }
Esempio n. 15
0
  @Override
  protected void startVmFromNewCreate(
      final StartNewCreatedVmInstanceMsg msg, final SyncTaskChain taskChain) {
    boolean callNext = true;
    try {
      refreshVO();
      ErrorCode allowed = validateOperationByState(msg, self.getState(), null);
      if (allowed != null) {
        bus.replyErrorByMessageType(msg, allowed);
        return;
      }
      ErrorCode preCreated = extEmitter.preStartNewCreatedVm(msg.getVmInstanceInventory());
      if (preCreated != null) {
        bus.replyErrorByMessageType(msg, preCreated);
        return;
      }

      StartNewCreatedApplianceVmMsg smsg = (StartNewCreatedApplianceVmMsg) msg;
      ApplianceVmSpec aspec = smsg.getApplianceVmSpec();

      final VmInstanceSpec spec = new VmInstanceSpec();
      spec.setVmInventory(msg.getVmInstanceInventory());
      if (msg.getL3NetworkUuids() != null && !msg.getL3NetworkUuids().isEmpty()) {
        SimpleQuery<L3NetworkVO> nwquery = dbf.createQuery(L3NetworkVO.class);
        nwquery.add(L3NetworkVO_.uuid, SimpleQuery.Op.IN, msg.getL3NetworkUuids());
        List<L3NetworkVO> vos = nwquery.list();
        List<L3NetworkInventory> nws = L3NetworkInventory.valueOf(vos);
        spec.setL3Networks(nws);
      } else {
        spec.setL3Networks(new ArrayList<L3NetworkInventory>(0));
      }

      if (msg.getDataDiskOfferingUuids() != null && !msg.getDataDiskOfferingUuids().isEmpty()) {
        SimpleQuery<DiskOfferingVO> dquery = dbf.createQuery(DiskOfferingVO.class);
        dquery.add(DiskOfferingVO_.uuid, SimpleQuery.Op.IN, msg.getDataDiskOfferingUuids());
        List<DiskOfferingVO> vos = dquery.list();

        // allow create multiple data volume from the same disk offering
        List<DiskOfferingInventory> disks = new ArrayList<DiskOfferingInventory>();
        for (final String duuid : msg.getDataDiskOfferingUuids()) {
          DiskOfferingVO dvo =
              CollectionUtils.find(
                  vos,
                  new Function<DiskOfferingVO, DiskOfferingVO>() {
                    @Override
                    public DiskOfferingVO call(DiskOfferingVO arg) {
                      if (duuid.equals(arg.getUuid())) {
                        return arg;
                      }
                      return null;
                    }
                  });
          disks.add(DiskOfferingInventory.valueOf(dvo));
        }
        spec.setDataDiskOfferings(disks);
      } else {
        spec.setDataDiskOfferings(new ArrayList<DiskOfferingInventory>(0));
      }

      ImageVO imvo = dbf.findByUuid(spec.getVmInventory().getImageUuid(), ImageVO.class);
      spec.getImageSpec().setInventory(ImageInventory.valueOf(imvo));

      spec.putExtensionData(ApplianceVmConstant.Params.applianceVmSpec.toString(), aspec);
      spec.setCurrentVmOperation(VmInstanceConstant.VmOperation.NewCreate);
      spec.putExtensionData(
          ApplianceVmConstant.Params.applianceVmSubType.toString(), getSelf().getApplianceVmType());

      changeVmStateInDb(VmInstanceStateEvent.starting);

      extEmitter.beforeStartNewCreatedVm(VmInstanceInventory.valueOf(self));
      FlowChain chain = apvmf.getCreateApplianceVmWorkFlowBuilder().build();
      chain.setName(String.format("create-appliancevm-%s", msg.getVmInstanceUuid()));
      chain.getData().put(VmInstanceConstant.Params.VmInstanceSpec.toString(), spec);
      chain
          .getData()
          .put(
              ApplianceVmConstant.Params.applianceVmFirewallRules.toString(),
              aspec.getFirewallRules());

      addBootstrapFlows(
          chain, VolumeFormat.getMasterHypervisorTypeByVolumeFormat(imvo.getFormat()));

      List<Flow> subCreateFlows = getPostCreateFlows();
      if (subCreateFlows != null) {
        for (Flow f : subCreateFlows) {
          chain.then(f);
        }
      }

      chain.then(
          new NoRollbackFlow() {
            String __name__ = "change-appliancevm-status-to-connected";

            @Override
            public void run(FlowTrigger trigger, Map data) {
              // must reload here, otherwise it will override changes created by previous flows
              self = dbf.reload(self);
              getSelf().setStatus(ApplianceVmStatus.Connected);
              dbf.update(self);
              trigger.next();
            }
          });

      boolean noRollbackOnFailure = ApplianceVmGlobalProperty.NO_ROLLBACK_ON_POST_FAILURE;
      chain.noRollback(noRollbackOnFailure);
      chain
          .done(
              new FlowDoneHandler(msg, taskChain) {
                @Override
                public void handle(Map data) {
                  VmInstanceSpec spec =
                      (VmInstanceSpec)
                          data.get(VmInstanceConstant.Params.VmInstanceSpec.toString());
                  self = dbf.reload(self);
                  self.setLastHostUuid(spec.getDestHost().getUuid());
                  self.setHostUuid(spec.getDestHost().getUuid());
                  self.setClusterUuid(spec.getDestHost().getClusterUuid());
                  self.setZoneUuid(spec.getDestHost().getZoneUuid());
                  self.setHypervisorType(spec.getDestHost().getHypervisorType());
                  self.setRootVolumeUuid(spec.getDestRootVolume().getUuid());
                  changeVmStateInDb(VmInstanceStateEvent.running);
                  logger.debug(
                      String.format(
                          "appliance vm[uuid:%s, name: %s, type:%s] is running ..",
                          self.getUuid(), self.getName(), getSelf().getApplianceVmType()));
                  VmInstanceInventory inv = VmInstanceInventory.valueOf(self);
                  extEmitter.afterStartNewCreatedVm(inv);
                  StartNewCreatedVmInstanceReply reply = new StartNewCreatedVmInstanceReply();
                  reply.setVmInventory(inv);
                  bus.reply(msg, reply);
                  taskChain.next();
                }
              })
          .error(
              new FlowErrorHandler(msg, taskChain) {
                @Override
                public void handle(ErrorCode errCode, Map data) {
                  extEmitter.failedToStartNewCreatedVm(VmInstanceInventory.valueOf(self), errCode);
                  dbf.remove(self);
                  StartNewCreatedVmInstanceReply reply = new StartNewCreatedVmInstanceReply();
                  reply.setError(errCode);
                  reply.setSuccess(false);
                  bus.reply(msg, reply);
                  taskChain.next();
                }
              })
          .start();

      callNext = false;
    } finally {
      if (callNext) {
        taskChain.next();
      }
    }
  }