/**
  * Concurrently stop the given number of vms other than this vm. Wait for the operations to
  * complete before returning.
  *
  * <p>Side effects: For any VM which is performing a NICE_KILL because of this call, it is marked
  * as such in the StopStartBB (blackboard). The blackboard will contain a key prefixed with
  * util.StopStartVMs.NiceKillInProgress and appended to with its VmId. The value of this key is
  * the true.
  *
  * <p>This blackboard entry is for the convenience of the caller, and it is up to the caller to
  * look for it or not. When a VM undergoes a NICE_KILL, the VM closes the cache and disconnects
  * from the distributed system. Any threads in that VM doing work can get exceptions during the
  * close and/or disconnect step. This blackboard entry is useful for those threads to allow
  * exceptions when they know an exception is possible.
  *
  * @param numVMsToStop The number of vms other than this vm to stop.
  * @returns A List of VmInfo which are stopped vms.
  */
 public static List stopVMs(int numVMsToStop) {
   Object[] anArr = StopStartVMs.getOtherVMs(numVMsToStop);
   List targetVmList = (List) (anArr[0]);
   List stopModeList = (List) (anArr[1]);
   stopStartVMs(targetVmList, stopModeList, true, false);
   return targetVmList;
 }
 /**
  * Concurrently stop and restart the specified number of VMs, other than this VM. The stop mode
  * for each VM is chosen from util.StopStartPrms.stopMode.
  *
  * <p>Side effects: see stopStartVMs(List, List).
  *
  * @param numToTarget The number of VMs, other than this VM, to stop and restart.
  * @throws TestException if there aren't numToTarget VMs available for stopping.
  */
 public static void stopStartOtherVMs(int numToTarget) {
   Log.getLogWriter()
       .info(
           "In stopStartVMs, attempting to stop/restart "
               + numToTarget
               + " vms (other than this one)");
   Object[] tmpArr = getOtherVMs(numToTarget);
   // get the VMs to stop; vmList and stopModeList are parallel lists
   List vmList = (List) (tmpArr[0]);
   List stopModeList = (List) (tmpArr[1]);
   StopStartVMs.stopStartVMs(vmList, stopModeList);
   Log.getLogWriter()
       .info(
           "In stopStartVMs, done with stop/restart "
               + numToTarget
               + " vms (other than this one)");
 }
  /**
   * Invokes AdminDistributedSystem.shutDownAllMembers() which disconnects all members but leaves
   * the vms up (because hydra threads remain) including the possibility of this vm being
   * disconnected, then this actually stops those vms (except this vm if it was targeted in the
   * shutDownAllMembers...this vm will remain up but disconnect). Stopped vms are stopped with
   * ON_DEMAND restart. This returns when the vms disconnected by shutDownAllMembers() (other than
   * this one) are all stopped .
   *
   * @param adminDS The admin distributed system instance to use to call shutdownAllMembers.
   * @param stopModes The stop modes to choose from.
   * @return An Array [0] List of {@link ClientVmInfo} instances describing the VMs that were
   *     stopped. [1] Set, the return from shutdownAllMembers()
   * @throws AdminException if the shutDownAllMembers call throws this exception.
   */
  public static Object[] shutDownAllMembers(
      AdminDistributedSystem adminDS, List<String> stopModes) {
    if (adminDS == null) {
      throw new HydraRuntimeException("AdminDistributedSystem cannot be null");
    }

    // Invoke shutDownAllMembers
    Log.getLogWriter().info("AdminDS " + adminDS + " is shutting down all members...");
    Set<DistributedMember> memberSet;
    try {
      long startTime = System.currentTimeMillis();
      memberSet = adminDS.shutDownAllMembers();
      long duration = System.currentTimeMillis() - startTime;
      Log.getLogWriter()
          .info(
              "AdminDS "
                  + adminDS
                  + " shut down (disconnected) the following members "
                  + "(vms remain up): "
                  + memberSet
                  + "; shutDownAll duration "
                  + duration
                  + "ms");
    } catch (AdminException e1) {
      throw new TestException(TestHelper.getStackTrace(e1));
    }

    // Now actually stop the vms.
    // First get the ClientVmInfos for the members that shutDownAllMembers
    // disconnected.
    List<ClientVmInfo> allClientInfos = new ArrayList(); // all members that were shutdown
    List<ClientVmInfo> allOtherClientInfos =
        new ArrayList(); // all members that were shutdown except this member
    ClientVmInfo thisClientInfo =
        null; // this member, or will remain null if this member was not shutdown
    List<String> stopModesToUse = new ArrayList();
    for (DistributedMember aMember : memberSet) {
      Integer vmId = null;
      try {
        vmId =
            new Integer(RemoteTestModule.Master.getVmid(aMember.getHost(), aMember.getProcessId()));
      } catch (java.rmi.RemoteException e) {
        throw new HydraRuntimeException("Unable to get vmID for " + aMember + ": " + e);
      }
      ClientVmInfo infoFromBB =
          (ClientVmInfo) StopStartBB.getBB().getSharedMap().get("StopStartVMInfo_for_vmid_" + vmId);
      String clientName = null;
      if (infoFromBB != null) {
        clientName = infoFromBB.getClientName();
      }
      ClientVmInfo info = new ClientVmInfo(vmId, clientName, null);
      allClientInfos.add(info);
      if (vmId == RemoteTestModule.getMyVmid()) {
        // shutdownAll disconnected this vm
        thisClientInfo = info;
      } else { // aMember is not the current vm
        allOtherClientInfos.add(info);
      }
      stopModesToUse.add(
          stopModes.get(TestConfig.tab().getRandGen().nextInt(0, stopModes.size() - 1)));
    }

    // now actually stop the vms; if this vm is included, do it last
    Object[] returnArr = new Object[2];
    if (thisClientInfo == null) { // shutDownAllMembers did not disconnect this vm
      // we can just stop all of them now and this vm lives on
      StopStartVMs.stopVMs(allClientInfos, stopModesToUse); // restart is ON_DEMAND
      returnArr[0] = allClientInfos;
    } else { // this vm was disconnected by shutDownAllMembers
      // first shutdown all other members except this one
      StopStartVMs.stopVMs(allOtherClientInfos, stopModesToUse.subList(0, stopModesToUse.size()));
      returnArr[0] = allOtherClientInfos;
    }
    returnArr[1] = memberSet;
    return returnArr;
  }