Wip 8665

@dmick @jcsp 
I am pretty happy with this.
There are still a few TODOs in the code and I've reached the point where I need some fresh eyes and sleep.
Created a new pull request to catch your attention.
I need to fix the minion-sim test variant for crush maps. It works fine against a real cluster.

Why do you want to set parent_bucket_by_node_id to None in the case of an empty dict?  Subsequent calls to .get will throw an exception.  Suggest returning an empty dict instead of None.