The biggest change is that the upgrade_groups() is a list of tuples ...
[()] ... rathern than a collections.OrderedDict(). This tends to make
more sense as they are processed in order and don't actually need to be
indexed.
Also excludes easyrsa (as it's not an upgrade target) and adds a
"Database Services" which upgrades mysql or percona FIRST before moving
on to rabbitmq and other stateful services. This is because some charms
really need to talk to mysql if one of the other stateful services does
a relation changed hook. This makes it more likely that the system will
ugprade correctly.
By including pre and pos-application functions, charm
series upgrades can be handled in a more generic way,
even when they require running additional actions
before a unit is upgraded, or after the whole application
is upgraded.
Updating each machine in a fully self-contained way makes
it easy to add per-machine and (possibly) per-application
post-upgrade function calls. This still performs the actual
series upgrades fully in parallel but will, for example,
start the do-release-upgrade on one unit while another is
still performing the initial dist-upgrade