Support replicas in a slice

ex:

  replicas: [
    { // replica
       slices: [
        { // slice
          replicas: [
            { volume: ... }, // replica of a slice
            { volume: ... }
          ]
        }
      ]
    }
  ]
Unify interfaces of Replicas to other related classes
Accept replica with no slice
Fold long line
Split method to generate slice instances
Split complex functions to simple one
Reuse single array to collect routes
Remove needless parameter
Fix typo
Fix mismatched arguments
Add more tests for deeply nested cases
Update expected catalog fragments for future V3 catalog
Restructure classes around Volume.

Now, there are 3 type volumes:

 1. SingleVolume, is a physical computer.
 2. SlicesVolume, is a collection of <Slice>s.
 2. ReplicasVolume, is a collection of volumes.

A Slice must have one of volumes.
For example:

  datasets:{
    Default:{
     replicas:[
       {
         slices:[
           { volume: { address:... } },
           {
             volume: {
               replicas: [
                 { address: ... },
                 { address: ... }
               ]
             }
           },
           {
             volume: {
               slices: [
                 { volume: { address:... } },
                 { volume: { address:... } },
                 {
                   volume: {
                     replicas: [
                       { address:... },
                       { address:... }
                     ]
                   }
                }
              ]
            }
          }
        ]
      }
    ]
  }}

It will be parsed as:

  ReplicasVolume:[
    Slices:[
      Slice:SingleVolume,
      Slice:ReplicasVolume:[
        SingleVolume,
        SingleVolume
      ],
      Slice:SlicesVolume:[
        Slice:SingleVolume,
        Slice:SingleVolume,
        Slice:ReplicasVolume:[
          SingleVolume,
          SingleVolume
        ]
      ]
    ]
  ]

Note, currently the top level ReplicasVolume is the Dataset itself.
It is dangerous, so we should change the structure like:

  datasets:{
    Default:{
      volume:{
        replicas:[...]
      }
    }
  }

This breaks backward compatibility - v2 catalogs have to be migrated when they are parsed.
So, after the change, catalog's spec version must be incremented to 3.
Collect routes by each replicas and slices, not the master dataset
Detect sliced or not by each volume
Use "volumes" instead of "replicas", because there is no class named "Replica"!
Detect sliced or not correctly for replicas volume
Fix typo
Use meaningful variable name instead of a generic name "data"
Unify and simplify methods to collect routes to "compute_routes"