private VirtualMachineRelocateSpec createRelocateSpec(
      PrintStream jLogger,
      boolean linkedClone,
      String resourcePoolName,
      String cluster,
      String datastoreName,
      boolean isResourcePoolRequired)
      throws RemoteException, MalformedURLException, VSphereException {
    VirtualMachineRelocateSpec rel = new VirtualMachineRelocateSpec();

    if (linkedClone) {
      rel.setDiskMoveType("createNewChildDiskBacking");
    } else {
      rel.setDiskMoveType("moveAllDiskBackingsAndDisallowSharing");
    }

    ClusterComputeResource clusterResource = getClusterByName(cluster);

    // probably only of interest if someone actually entered a cluster name
    if (clusterResource == null && StringUtils.isNotBlank(cluster)) {
      logMessage(
          jLogger,
          "Cluster resource "
              + cluster
              + " does not exist, root folder will be used for getting resource pool and datastore");
    }

    if (resourcePoolName != null && !resourcePoolName.isEmpty()) {
      ResourcePool resourcePool = getResourcePoolByName(resourcePoolName, clusterResource);

      if (resourcePool == null) {
        throw new VSphereException("Resource pool \"" + resourcePoolName + "\" not found");
      }

      rel.setPool(resourcePool.getMOR());
    } else if (isResourcePoolRequired) {
      throw new VSphereException("You must specify a resource  pool  when using a template");
    }

    if (datastoreName != null && !datastoreName.isEmpty()) {
      Datastore datastore = getDatastoreByName(datastoreName, clusterResource);
      if (datastore == null) {
        throw new VSphereException("Datastore \"" + datastoreName + "\" not found!");
      }
      rel.setDatastore(datastore.getMOR());
    }

    return rel;
  }
 /**
  * Clones a new VM from a given vm or template with a given name.
  *
  * @param cloneName - name of VM to be created
  * @param sourceName - name of VM or template to be cloned
  * @param linkedClone - true if you want to re-use disk backings
  * @param resourcePoolName - resource pool to use
  * @param cluster - ComputeClusterResource to use
  * @param datastoreName - Datastore to use
  * @throws VSphereException
  */
 public void cloneVm(
     String cloneName,
     String sourceName,
     boolean linkedClone,
     String resourcePoolName,
     String cluster,
     String datastoreName,
     boolean powerOn,
     PrintStream jLogger)
     throws VSphereException {
   boolean DO_USE_SNAPSHOTS = true;
   logMessage(
       jLogger, "Creating a shallow clone of \"" + sourceName + "\" to \"" + cloneName + "\"");
   cloneOrDeployVm(
       cloneName,
       sourceName,
       linkedClone,
       resourcePoolName,
       cluster,
       datastoreName,
       DO_USE_SNAPSHOTS,
       powerOn,
       jLogger);
 }
 /**
  * Deploys a new VM from a given template with a given name.
  *
  * @param cloneName - name of VM to be created
  * @param sourceName - name of VM or template to be cloned
  * @param linkedClone - true if you want to re-use disk backings
  * @param resourcePoolName - resource pool to use
  * @param cluster - ComputeClusterResource to use
  * @param datastoreName - Datastore to use
  * @throws VSphereException
  */
 public void deployVm(
     String cloneName,
     String sourceName,
     boolean linkedClone,
     String resourcePoolName,
     String cluster,
     String datastoreName,
     boolean powerOn,
     PrintStream jLogger)
     throws VSphereException {
   boolean DO_NOT_USE_SNAPSHOTS = false;
   logMessage(
       jLogger, "Deploying new vm \"" + cloneName + "\" from template \"" + sourceName + "\"");
   cloneOrDeployVm(
       cloneName,
       sourceName,
       linkedClone,
       resourcePoolName,
       cluster,
       datastoreName,
       DO_NOT_USE_SNAPSHOTS,
       powerOn,
       jLogger);
 }
  private void cloneOrDeployVm(
      String cloneName,
      String sourceName,
      boolean linkedClone,
      String resourcePoolName,
      String cluster,
      String datastoreName,
      boolean useSnapshot,
      boolean powerOn,
      PrintStream jLogger)
      throws VSphereException {
    try {
      VirtualMachine sourceVm = getVmByName(sourceName);

      if (sourceVm == null) {
        throw new VSphereException("VM or template \"" + sourceName + "\" not found");
      }

      if (getVmByName(cloneName) != null) {
        throw new VSphereException("VM \"" + cloneName + "\" already exists");
      }

      VirtualMachineRelocateSpec rel =
          createRelocateSpec(
              jLogger,
              linkedClone,
              resourcePoolName,
              cluster,
              datastoreName,
              sourceVm.getConfig().template);

      VirtualMachineCloneSpec cloneSpec = createCloneSpec(rel);
      cloneSpec.setTemplate(false);
      cloneSpec.powerOn = powerOn;

      if (useSnapshot) {
        // TODO add config to allow state of VM or snapshot
        if (sourceVm.getCurrentSnapShot() == null) {
          throw new VSphereException(
              "Source VM or Template \"" + sourceName + "\" requires at least one snapshot!");
        }
        cloneSpec.setSnapshot(sourceVm.getCurrentSnapShot().getMOR());
      }

      Task task = sourceVm.cloneVM_Task((Folder) sourceVm.getParent(), cloneName, cloneSpec);
      logMessage(jLogger, "Started cloning of VM. Please wait ...");

      String status = task.waitForTask();
      if (!TaskInfoState.success.toString().equals(status)) {
        throw new VSphereException(
            "Couldn't clone \""
                + sourceName
                + "\"! Does \""
                + cloneName
                + "\" already exist? "
                + "Clone task ended with status "
                + status);
      }

    } catch (Exception e) {
      throw new VSphereException(e);
    }
  }