private void startNewWorkers(
      Set<Integer> keepPorts, Map<Integer, LocalAssignment> localAssignments) throws Exception {
    /**
     * Step 4: get reassigned tasks, which is in assignedTasks, but not in keeperPorts Map<port(type
     * Integer), LocalAssignment>
     */
    Map<Integer, LocalAssignment> newWorkers =
        JStormUtils.select_keys_pred(keepPorts, localAssignments);

    /** Step 5: generate new work ids */
    Map<Integer, String> newWorkerIds = new HashMap<Integer, String>();

    for (Entry<Integer, LocalAssignment> entry : newWorkers.entrySet()) {
      Integer port = entry.getKey();
      LocalAssignment assignment = entry.getValue();

      String workerId = UUID.randomUUID().toString();

      newWorkerIds.put(port, workerId);

      // create new worker Id directory
      // LOCALDIR/workers/newworkid/pids
      try {
        StormConfig.worker_pids_root(conf, workerId);
      } catch (IOException e1) {
        LOG.error("Failed to create " + workerId + " localdir", e1);
        throw e1;
      }

      StringBuilder sb = new StringBuilder();
      sb.append("Launching worker with assiangment ");
      sb.append(assignment.toString());
      sb.append(" for the supervisor ");
      sb.append(supervisorId);
      sb.append(" on port ");
      sb.append(port);
      sb.append(" with id ");
      sb.append(workerId);
      LOG.info(sb);

      try {
        String clusterMode = StormConfig.cluster_mode(conf);

        if (clusterMode.equals("distributed")) {
          launchWorker(
              conf,
              sharedContext,
              assignment.getTopologyId(),
              supervisorId,
              port,
              workerId,
              assignment);
        } else if (clusterMode.equals("local")) {
          launchWorker(
              conf,
              sharedContext,
              assignment.getTopologyId(),
              supervisorId,
              port,
              workerId,
              workerThreadPids);
        }
      } catch (Exception e) {
        String errorMsg = "Failed to launchWorker workerId:" + workerId + ":" + port;
        LOG.error(errorMsg, e);
        throw e;
      }
    }

    /** FIXME, workerIds should be Set, not Collection, but here simplify the logic */
    Collection<String> workerIds = newWorkerIds.values();
    try {
      waitForWorkersLaunch(conf, workerIds);
    } catch (IOException e) {
      LOG.error(e + " waitForWorkersLaunch failed");
    } catch (InterruptedException e) {
      LOG.error(e + " waitForWorkersLaunch failed");
    }
  }