Esempio n. 1
0
  @Override
  public Flow marshalVmOperationFlow(
      String previousFlowName, String nextFlowName, FlowChain chain, VmInstanceSpec spec) {
    if (VmAllocatePrimaryStorageFlow.class.getName().equals(nextFlowName)) {
      if (spec.getCurrentVmOperation() == VmOperation.NewCreate) {
        if (getLocalStorageInCluster(spec.getDestHost().getClusterUuid()) != null) {
          return new LocalStorageAllocateCapacityFlow();
        }
      }
    } else if (spec.getCurrentVmOperation() == VmOperation.AttachVolume) {
      VolumeInventory volume = spec.getDestDataVolumes().get(0);
      if (VolumeStatus.NotInstantiated.toString().equals(volume.getStatus())
          && VmAllocatePrimaryStorageForAttachingDiskFlow.class.getName().equals(nextFlowName)) {
        if (isRootVolumeOnLocalStorage(spec.getVmInventory().getRootVolumeUuid())) {
          return new LocalStorageAllocateCapacityForAttachingVolumeFlow();
        }
      }
    } else if (spec.getCurrentVmOperation() == VmOperation.Migrate
        && isRootVolumeOnLocalStorage(spec.getVmInventory().getRootVolumeUuid())
        && VmMigrateOnHypervisorFlow.class.getName().equals(nextFlowName)) {
      if (KVMConstant.KVM_HYPERVISOR_TYPE.equals(spec.getVmInventory().getHypervisorType())) {
        return new LocalStorageKvmMigrateVmFlow();
      } else {
        throw new OperationFailureException(
            errf.stringToOperationError(
                String.format(
                    "local storage doesn't support live migration for hypervisor[%s]",
                    spec.getVmInventory().getHypervisorType())));
      }
    }

    return null;
  }
  @Override
  public void run(final FlowTrigger trigger, final Map data) {
    final VmInstanceSpec spec =
        (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString());
    VolumeInventory volume = spec.getDestDataVolumes().get(0);

    SimpleQuery<LocalStorageResourceRefVO> q = dbf.createQuery(LocalStorageResourceRefVO.class);
    q.select(LocalStorageResourceRefVO_.hostUuid, LocalStorageResourceRefVO_.primaryStorageUuid);
    q.add(
        LocalStorageResourceRefVO_.resourceUuid, Op.EQ, spec.getVmInventory().getRootVolumeUuid());
    Tuple t = q.findTuple();
    final String hostUuid = t.get(0, String.class);
    String priUuid = t.get(1, String.class);

    AllocatePrimaryStorageMsg msg = new AllocatePrimaryStorageMsg();
    if (isThereOtherStorageForTheHost(hostUuid, priUuid)) {
      // use network-shared primary storage
      msg.addExcludeAllocatorStrategy(LocalStorageConstants.LOCAL_STORAGE_ALLOCATOR_STRATEGY);
      msg.addExcludePrimaryStoratgeUuid(priUuid);
    } else {
      msg.setAllocationStrategy(LocalStorageConstants.LOCAL_STORAGE_ALLOCATOR_STRATEGY);
      msg.setRequiredPrimaryStorageUuid(
          spec.getVmInventory().getRootVolume().getPrimaryStorageUuid());
    }

    msg.setRequiredHostUuid(hostUuid);
    msg.setVmInstanceUuid(spec.getVmInventory().getUuid());
    msg.setSize(volume.getSize());
    msg.setPurpose(PrimaryStorageAllocationPurpose.CreateVolume.toString());
    bus.makeLocalServiceId(msg, PrimaryStorageConstant.SERVICE_ID);
    bus.send(
        msg,
        new CloudBusCallBack(trigger) {
          @Override
          public void run(MessageReply reply) {
            if (!reply.isSuccess()) {
              trigger.fail(reply.getError());
              return;
            }

            spec.setDestHost(HostInventory.valueOf(dbf.findByUuid(hostUuid, HostVO.class)));

            AllocatePrimaryStorageReply ar = (AllocatePrimaryStorageReply) reply;
            data.put(
                VmInstanceConstant.Params.DestPrimaryStorageInventoryForAttachingVolume.toString(),
                ar.getPrimaryStorageInventory());
            data.put(LocalStorageAllocateCapacityForAttachingVolumeFlow.class, ar.getSize());
            trigger.next();
          }
        });
  }
  private void releaseNetworkServices(
      final VmInstanceSpec spec,
      NetworkServiceExtensionPosition position,
      final NoErrorCompletion completion) {
    if (!spec.getVmInventory().getType().equals(VmInstanceConstant.USER_VM_TYPE)) {
      completion.done();
      return;
    }

    if (nsExts.isEmpty()) {
      completion.done();
      return;
    }

    // we run into this situation when VM nics are all detached and the
    // VM is being rebooted
    if (spec.getDestNics().isEmpty()) {
      completion.done();
      return;
    }

    List<String> nsTypes = spec.getRequiredNetworkServiceTypes();

    FlowChain schain =
        FlowChainBuilder.newSimpleFlowChain()
            .setName(
                String.format(
                    "release-network-services-from-vm-%s", spec.getVmInventory().getUuid()));
    schain.allowEmptyFlow();

    for (final NetworkServiceExtensionPoint ns : nsExts) {
      if (position != null && ns.getNetworkServiceExtensionPosition() != position) {
        continue;
      }

      if (!nsTypes.contains(ns.getNetworkServiceType().toString())) {
        continue;
      }

      NoRollbackFlow flow =
          new NoRollbackFlow() {
            String __name__ =
                String.format("release-network-service-%s", ns.getNetworkServiceType());

            @Override
            public void run(final FlowTrigger chain, Map data) {
              logger.debug(
                  String.format(
                      "NetworkServiceExtensionPoint[%s] is asking back ends to release network service[%s] if needed",
                      ns.getClass().getName(), ns.getNetworkServiceType()));
              ns.releaseNetworkService(
                  spec,
                  data,
                  new NoErrorCompletion() {
                    @Override
                    public void done() {
                      chain.next();
                    }
                  });
            }
          };

      schain.then(flow);
    }

    schain
        .done(
            new FlowDoneHandler(completion) {
              @Override
              public void handle(Map data) {
                logger.debug(
                    String.format(
                        "successfully released network services for vm[uuid:%s,  name:%s]",
                        spec.getVmInventory().getUuid(), spec.getVmInventory().getName()));
                completion.done();
              }
            })
        .start();
  }
Esempio n. 4
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();
      }
    }
  }