Subject: bug#36855: guix system switch-generation doesn't

From: Chris Marusich <[email-masked]>
Date: Thu, 08 Aug 2019 09:40:30 -0700

Hi Jakob,

[email-masked] (Jakob L. Kreuze) writes:

> 'switch-to-system-generation' doesn't call out to
> 'upgrade-shepherd-services'. I'm not sure if this was an intentional
> decision or not

It is intentional, but only because there is currently no way to call
upgrade-shepherd-services when switching system generations.

Consider the procedure upgrade-shepherd-services: you must pass it an
<operating-system> record.  When you are flipping from one generation to
another, how do you get the <operating-system> record that was used for
the generation you're switching to?  Guix doesn't currently store the
operating system configuration file or its <operating-system> record
anywhere, so we can't call upgrade-shepherd-services.

This was discussed in 2016 and we agreed we need to persist some
information to enable us to handle Shepherd services correctly.  This is
what Ludo suggested at the time:

https://lists.gnu.org/archive/html/guix-devel/2016-06/msg00173.html

"Maybe we could store in the system output (result of ‘guix system
build’) an sexp representation of (part of) our <shepherd-service>
records:

  (shepherd-service
    (provisions (x y z))
    (requirements (a b c))
    (start-script "/gnu/store/…-start-foo.scm")
    (stop-script "/gnu/store/…-stop-foo.scm")
    …)

Then ‘upgrade-shepherd-services’ could start from this simplified
representation instead of using the full-blown <shepherd-service>
objects, and thus could work both when instantiating a new generation
and when rolling back."

Until that happens, you'll always have to reboot to complete the
switch.

FYI, last I checked (about 3 years ago), in NixOS they took a slightly
different approach: instead of storing state describing the previous
system generation and relying on the current system's logic to correctly
parse it and use it to revert the system to a prior configuration, they
just dump everything into a self-contained script that knows how to
update the entire system to one specific configuration.  That approach
is nice in some ways because switching generations is dead simple - you
just run the switching script belonging to the generation you want to
switch to - but it also has downsides.

For example, if the target generation is old enough compared to the
current system, then the target generation's old switching script might
not understand how to deal with the current system correctly.  Instead,
if you only store the bare minimum of state required to take the right
actions, and you implement the meat of the logic in the current Guix
installation, you are more likely to be able to switch generations even
to very old ones where the world was very different, since the current
Guix can be taught how to deal gracefully with the old world.  But it
seems more complicated.  It's all about trade-offs.

That said, I've never gone back to implement this.  If you want to give
it a try, you're more than welcome to do so!

-- 
Chris