public static void main(String[] args) {
    int numDataNodes = 0;
    int numRacks = 0;
    boolean inject = false;
    long startingBlockId = 1;
    int numBlocksPerDNtoInject = 0;
    int replication = 1;

    Configuration conf = new HdfsConfiguration();

    for (int i = 0; i < args.length; i++) { // parse command line
      if (args[i].equals("-n")) {
        if (++i >= args.length || args[i].startsWith("-")) {
          printUsageExit("missing number of nodes");
        }
        numDataNodes = Integer.parseInt(args[i]);
      } else if (args[i].equals("-racks")) {
        if (++i >= args.length || args[i].startsWith("-")) {
          printUsageExit("Missing number of racks");
        }
        numRacks = Integer.parseInt(args[i]);
      } else if (args[i].equals("-r")) {
        if (++i >= args.length || args[i].startsWith("-")) {
          printUsageExit("Missing replicaiton factor");
        }
        replication = Integer.parseInt(args[i]);
      } else if (args[i].equals("-d")) {
        if (++i >= args.length || args[i].startsWith("-")) {
          printUsageExit("Missing datanode dirs parameter");
        }
        dataNodeDirs = args[i];
      } else if (args[i].equals("-simulated")) {
        conf.setBoolean(SimulatedFSDataset.CONFIG_PROPERTY_SIMULATED, true);
      } else if (args[i].equals("-inject")) {
        if (!conf.getBoolean(SimulatedFSDataset.CONFIG_PROPERTY_SIMULATED, false)) {
          System.out.print("-inject is valid only for simulated");
          printUsageExit();
        }
        inject = true;
        if (++i >= args.length || args[i].startsWith("-")) {
          printUsageExit("Missing starting block and number of blocks per DN to inject");
        }
        startingBlockId = Integer.parseInt(args[i]);
        if (++i >= args.length || args[i].startsWith("-")) {
          printUsageExit("Missing number of blocks to inject");
        }
        numBlocksPerDNtoInject = Integer.parseInt(args[i]);
      } else {
        printUsageExit();
      }
    }
    if (numDataNodes <= 0 || replication <= 0) {
      printUsageExit("numDataNodes and replication have to be greater than zero");
    }
    if (replication > numDataNodes) {
      printUsageExit("Replication must be less than or equal to numDataNodes");
    }
    String nameNodeAdr = FileSystem.getDefaultUri(conf).getAuthority();
    if (nameNodeAdr == null) {
      System.out.println("No name node address and port in config");
      System.exit(-1);
    }
    boolean simulated = conf.getBoolean(SimulatedFSDataset.CONFIG_PROPERTY_SIMULATED, false);
    System.out.println(
        "Starting "
            + numDataNodes
            + (simulated ? " Simulated " : " ")
            + " Data Nodes that will connect to Name Node at "
            + nameNodeAdr);

    System.setProperty("test.build.data", dataNodeDirs);

    MiniDFSCluster mc = new MiniDFSCluster();
    try {
      mc.formatDataNodeDirs();
    } catch (IOException e) {
      System.out.println("Error formating data node dirs:" + e);
    }

    String[] rack4DataNode = null;
    if (numRacks > 0) {
      System.out.println("Using " + numRacks + " racks: ");
      String rackPrefix = getUniqueRackPrefix();

      rack4DataNode = new String[numDataNodes];
      for (int i = 0; i < numDataNodes; ++i) {
        // rack4DataNode[i] = racks[i%numRacks];
        rack4DataNode[i] = rackPrefix + "-" + i % numRacks;
        System.out.println("Data Node " + i + " using " + rack4DataNode[i]);
      }
    }
    try {
      mc.startDataNodes(conf, numDataNodes, true, StartupOption.REGULAR, rack4DataNode);
      if (inject) {
        long blockSize = 10;
        System.out.println(
            "Injecting "
                + numBlocksPerDNtoInject
                + " blocks in each DN starting at blockId "
                + startingBlockId
                + " with blocksize of "
                + blockSize);
        Block[] blocks = new Block[numBlocksPerDNtoInject];
        long blkid = startingBlockId;
        for (int i_dn = 0; i_dn < numDataNodes; ++i_dn) {
          for (int i = 0; i < blocks.length; ++i) {
            blocks[i] = new Block(blkid++, blockSize, CreateEditsLog.BLOCK_GENERATION_STAMP);
          }
          for (int i = 1; i <= replication; ++i) {
            // inject blocks for dn_i into dn_i and replica in dn_i's neighbors
            mc.injectBlocks((i_dn + i - 1) % numDataNodes, Arrays.asList(blocks));
            System.out.println(
                "Injecting blocks of dn " + i_dn + " into dn" + ((i_dn + i - 1) % numDataNodes));
          }
        }
        System.out.println("Created blocks from Bids " + startingBlockId + " to " + (blkid - 1));
      }

    } catch (IOException e) {
      System.out.println("Error creating data node:" + e);
    }
  }