public int printTopology() throws IOException {
    DistributedFileSystem dfs = getDFS();
    final DatanodeInfo[] report = dfs.getDataNodeStats();

    // Build a map of rack -> nodes from the datanode report
    Map<String, HashMap<String, String>> map = new HashMap<>();
    for(DatanodeInfo dni : report) {
      String location = dni.getNetworkLocation();
      String name = dni.getName();
      String dnState = dni.getAdminState().toString();
        
      if(!map.containsKey(location)) {
        map.put(location, new HashMap<>());
      }

      Map<String, String> node = map.get(location);
      node.put(name, dnState);
    }
      
    // Sort the racks (and nodes) alphabetically, display in order
    List<String> racks = new ArrayList<>(map.keySet());
    Collections.sort(racks);
      
    for(String r : racks) {
      System.out.println("Rack: " + r);
      Map<String, String> nodes = map.get(r);

      for(Map.Entry<String, String> entry : nodes.entrySet()) {
        String n = entry.getKey();
        System.out.print("   " + n);
        String hostname = NetUtils.getHostNameOfIP(n);
        if(hostname != null) {
          System.out.print(" (" + hostname + ")");
        }
        System.out.print(" " + entry.getValue());
        System.out.println();
      }

      System.out.println();
    }
    return 0;
  }
@Test(timeout = 30000)
  public void testPrintTopology() throws Exception {
    redirectStream();

    /* init conf */
    final Configuration dfsConf = new HdfsConfiguration();
    final File baseDir = new File(
        PathUtils.getTestDir(getClass()),
        GenericTestUtils.getMethodName());
    dfsConf.set(MiniDFSCluster.HDFS_MINIDFS_BASEDIR, baseDir.getAbsolutePath());

    final int numDn = 4;
    final String[] racks = {
        "/d1/r1", "/d1/r2",
        "/d2/r1", "/d2/r2"};

    /* init cluster using topology */
    try (MiniDFSCluster miniCluster = new MiniDFSCluster.Builder(dfsConf)
        .numDataNodes(numDn).racks(racks).build()) {

      miniCluster.waitActive();
      assertEquals(numDn, miniCluster.getDataNodes().size());
      final DFSAdmin dfsAdmin = new DFSAdmin(dfsConf);

      resetStream();
      final int ret = ToolRunner.run(dfsAdmin, new String[] {"-printTopology"});

      /* collect outputs */
      final List<String> outs = Lists.newArrayList();
      scanIntoList(out, outs);

      /* verify results */
      assertEquals(0, ret);
      assertEquals(
          "There should be three lines per Datanode: the 1st line is"
              + " rack info, 2nd node info, 3rd empty line. The total"
              + " should be as a result of 3 * numDn.",
          12, outs.size());
      assertThat(outs.get(0),
          is(allOf(containsString("Rack:"), containsString("/d1/r1"))));
      assertThat(outs.get(3),
          is(allOf(containsString("Rack:"), containsString("/d1/r2"))));
      assertThat(outs.get(6),
          is(allOf(containsString("Rack:"), containsString("/d2/r1"))));
      assertThat(outs.get(9),
          is(allOf(containsString("Rack:"), containsString("/d2/r2"))));
    }
  }