@Override
  public VM getVM(VmConfiguration configuration, int whichVM) {
    if (whichVM == DUnitLauncher.DEBUGGING_VM_NUM) {
      // for ease of debugging, pass -1 to get the local VM
      return debuggingVM;
    }

    if (whichVM < getVMCount()) {
      VM current = super.getVM(whichVM);
      if (!current.getConfiguration().equals(configuration)) {
        current.bounce(configuration, false);
      }
      return current;
    }

    int oldVMCount = getVMCount();
    if (whichVM >= oldVMCount) {
      // If we don't have a VM with that number, dynamically create it.
      try {
        // first fill in any gaps, to keep the superclass, Host, happy
        for (int i = oldVMCount; i < whichVM; i++) {
          processManager.launchVM(i);
        }
        processManager.waitForVMs(DUnitLauncher.STARTUP_TIMEOUT);

        for (int i = oldVMCount; i < whichVM; i++) {
          addVM(i, VmConfiguration.current(), processManager.getStub(i),
              processManager.getProcessHolder(i), processManager);
        }

        // now create the one we really want
        processManager.launchVM(configuration, whichVM, false, 0);
        processManager.waitForVMs(DUnitLauncher.STARTUP_TIMEOUT);
        addVM(whichVM, configuration, processManager.getStub(whichVM),
            processManager.getProcessHolder(whichVM), processManager);

      } catch (IOException | InterruptedException | NotBoundException e) {
        throw new RuntimeException("Could not dynamically launch vm + " + whichVM, e);
      }
    }

    return super.getVM(whichVM);
  }
Retrieves one of this host's VMs based on the specified VM ID. This will not bounce VM to a
different version. It will only get the current running VM or launch a new one if not already
launched.

@param n ID of the requested VM; a value of <code>-1</code> will return the controller VM,
       which may be useful for debugging.
@return VM for the requested VM ID.
geode-dunit/src/main/java/org/apache/geode/test/dunit/internal/DUnitHost.java