public void deleteSnapshot(
      String vmName, String snapName, boolean consolidate, boolean failOnNoExist)
      throws VSphereException {

    VirtualMachine vm = getVmByName(vmName);
    VirtualMachineSnapshot snap = getSnapshotInTree(vm, snapName);

    if (snap == null && failOnNoExist) {
      throw new VSphereException("Virtual Machine snapshot cannot be found");
    }

    try {

      Task task;
      if (snap != null) {
        // Does not delete subtree; Implicitly consolidates disk
        task = snap.removeSnapshot_Task(false);
        if (!task.waitForTask().equals(Task.SUCCESS)) {
          throw new VSphereException("Could not delete snapshot");
        }
      }

      if (!consolidate) return;

      // This might be redundant, but I think it consolidates all disks,
      // where as the removeSnapshot only consolidates the individual disk
      task = vm.consolidateVMDisks_Task();
      if (!task.waitForTask().equals(Task.SUCCESS)) {
        throw new VSphereException("Could not consolidate VM disks");
      }
    } catch (Exception e) {
      throw new VSphereException(e);
    }
  }
  public static void main(String[] args) throws Exception {
    if (args.length != 5) {
      System.out.println("Usage: java VMpowerOps <url> " + "<username> <password> <vmname> <op>");
      System.out.println("op - reboot|poweron|poweroff" + "|reset|standby|suspend|shutdown");
      System.exit(0);
    }

    String vmname = args[3];
    String op = args[4];

    ServiceInstance si = new ServiceInstance(new URL(args[0]), args[1], args[2], true);

    Folder rootFolder = si.getRootFolder();
    VirtualMachine vm =
        (VirtualMachine)
            new InventoryNavigator(rootFolder).searchManagedEntity("VirtualMachine", vmname);

    if (vm == null) {
      System.out.println("No VM " + vmname + " found");
      si.getServerConnection().logout();
      return;
    }

    if ("reboot".equalsIgnoreCase(op)) {
      vm.rebootGuest();
      System.out.println(vmname + " guest OS rebooted");
    } else if ("poweron".equalsIgnoreCase(op)) {
      Task task = vm.powerOnVM_Task(null);
      if (task.waitForMe() == Task.SUCCESS) {
        System.out.println(vmname + " powered on");
      }
    } else if ("poweroff".equalsIgnoreCase(op)) {
      Task task = vm.powerOffVM_Task();
      if (task.waitForMe() == Task.SUCCESS) {
        System.out.println(vmname + " powered off");
      }
    } else if ("reset".equalsIgnoreCase(op)) {
      Task task = vm.resetVM_Task();
      if (task.waitForMe() == Task.SUCCESS) {
        System.out.println(vmname + " reset");
      }
    } else if ("standby".equalsIgnoreCase(op)) {
      vm.standbyGuest();
      System.out.println(vmname + " guest OS stoodby");
    } else if ("suspend".equalsIgnoreCase(op)) {
      Task task = vm.suspendVM_Task();
      if (task.waitForMe() == Task.SUCCESS) {
        System.out.println(vmname + " suspended");
      }
    } else if ("shutdown".equalsIgnoreCase(op)) {
      Task task = vm.suspendVM_Task();
      if (task.waitForMe() == Task.SUCCESS) {
        System.out.println(vmname + " suspended");
      }
    } else {
      System.out.println("Invalid operation. Exiting...");
    }
    si.getServerConnection().logout();
  }
  public void takeSnapshot(String vmName, String snapshot, String description, boolean snapMemory)
      throws VSphereException {

    VirtualMachine vmToSnapshot = getVmByName(vmName);
    if (vmToSnapshot == null) {
      throw new VSphereException("Vm " + vmName + " was not found");
    }
    try {
      Task task = vmToSnapshot.createSnapshot_Task(snapshot, description, snapMemory, !snapMemory);
      if (task.waitForTask().equals(Task.SUCCESS)) {
        return;
      }
    } catch (Exception e) {
      throw new VSphereException(e);
    }

    throw new VSphereException("Could not take snapshot");
  }
  public void revertToSnapshot(String vmName, String snapName) throws VSphereException {

    VirtualMachine vm = getVmByName(vmName);
    VirtualMachineSnapshot snap = getSnapshotInTree(vm, snapName);

    if (snap == null) {
      throw new VSphereException("Virtual Machine snapshot cannot be found");
    }

    try {
      Task task = snap.revertToSnapshot_Task(null);
      if (!task.waitForTask().equals(Task.SUCCESS)) {
        throw new VSphereException("Could not revert to snapshot");
      }
    } catch (Exception e) {
      throw new VSphereException(e);
    }
  }
  public void reconfigureVm(String name, VirtualMachineConfigSpec spec) throws VSphereException {
    VirtualMachine vm = getVmByName(name);

    if (vm == null) {
      throw new VSphereException("No VM or template " + name + " found");
    }
    System.out.println("Reconfiguring VM. Please wait ...");
    try {
      Task task = vm.reconfigVM_Task(spec);
      String status = task.waitForTask();
      if (status.equals(TaskInfoState.success.toString())) {
        return;
      }
    } catch (Exception e) {
      throw new VSphereException("VM cannot be reconfigured:" + e.getMessage(), e);
    }
    throw new VSphereException("Couldn't reconfigure \"" + name + "\"!");
  }
  /**
   * @param name - Name of VM to start
   * @throws VSphereException
   */
  public void startVm(String name, int timeoutInSeconds) throws VSphereException {

    try {
      VirtualMachine vm = getVmByName(name);
      if (vm == null) {
        throw new VSphereException("Vm " + name + " was not found");
      }
      if (isPoweredOn(vm)) return;

      if (vm.getConfig().template) throw new VSphereException("VM represents a template!");

      Task task = vm.powerOnVM_Task(null);

      int timesToCheck = timeoutInSeconds / 5;
      // add one extra time for remainder
      timesToCheck++;
      System.out.println("Checking " + timesToCheck + " times for vm to be powered on");

      for (int i = 0; i < timesToCheck; i++) {

        if (task.getTaskInfo().getState() == TaskInfoState.success) {
          System.out.println("VM was powered up successfully.");
          return;
        }

        if (task.getTaskInfo().getState() == TaskInfoState.running
            || task.getTaskInfo().getState() == TaskInfoState.queued) {
          Thread.sleep(5000);
        }

        // Check for copied/moved question
        VirtualMachineQuestionInfo q = vm.getRuntime().getQuestion();
        if (q != null && q.getId().equals("_vmx1")) {
          vm.answerVM(q.getId(), q.getChoice().getDefaultIndex().toString());
          return;
        }
      }
    } catch (Exception e) {
      throw new VSphereException("VM cannot be started: " + e.getMessage(), e);
    }

    throw new VSphereException("VM cannot be started");
  }
  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);
    }
  }