mgr/volumes: tie everything together to implement versioned subvolumes
apart from the new way of provisioning subvolumes, this makes heavy
use of context manager for volumes, groups and subvolumes.
this change classifies volumes, groups and subvolumes to be treated
as filesystem dentries and inodes. a "volume" can be thought as a
dentry with "groups" as it's entries (inodes). likewise, a "group"
is a dentry again with "subvolumes" as entries (inodes). this is
built into the access mechanism as follows:
with open_volume(...) as fs_handle:
with open_gorup(fs_handle, ...) as group:
with open_subvolume(group, ...) as subvolume:
# call subvolume object API
path = subvolume.getpath()
this way, lot of redundant checks such as verifying if a volume or
group exist before accessing a subvolume is built right into the
access mechanism, plus, an added bonus of simple error handling.