Patchwork Seeking guidance regarding system roll-back and switch-generation

login
register
mail settings
Submitter Ludovic Courtès
Date July 22, 2016, 3:49 p.m.
Message ID <87vazxk70h.fsf@gnu.org>
Download mbox | patch
Permalink /patch/13928/
State New
Headers show

Comments

Ludovic Courtès - July 22, 2016, 3:49 p.m.
Hi!

Chris Marusich <cmmarusich@gmail.com> skribis:

> Thank you very much for taking the time to respond!  Now I have a better
> idea of how to proceed.

Sorry for the delay!  That’s what you get for asking difficult
questions.  ;-)

> ludo@gnu.org (Ludovic Courtès) writes:
>
>> Chris Marusich <cmmarusich@gmail.com> skribis:
>>
>>> I've noticed that the GuixSD mechanism is different from the NixOS
>>> mechanism.  In particular, NixOS uses an "install-grub" script (which is
>>> specific to each system generation) to install grub, but GuixSD does
>>> not.  Is this difference intentional?
>>
>> Looking at
>> <https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/boot/loader/grub/install-grub.pl>,
>> part of it seems to be concerned with the generation of grub.cfg, which
>> is what (gnu system grub) does.
>>
>> It also does a couple more things, such as providing proper EFI support,
>> and avoiding reinstalling GRUB when possible (whereas ‘guix system
>> reconfigure’ currently reruns ‘grub-install’ each time, even when it’s
>> not strictly needed.)
>>
>> So I don’t think it’s very different, after all.  Or am I missing
>> something?
>
> Yes, they both install grub, but the mechanism seems different.  NixOS
> generates a script for each system generation, which installs exactly
> the right grub for that generation.  Unless I'm mistaken, GuixSD does
> not do that.  Instead, the existing GuixSD mechanism seems to require an
> operating system configuration file.  GuixSD uses that to determine the
> correct grub, which it then installs.

Sure, but it seems to be equivalent in the end.

>> Switching to a generations primarily means: (1) running the target’s
>> activation script, (2) updating Shepherd services, and (3) updating
>> grub.cfg.
>
> In addition to (3), don't we also need to install the grub software
> itself?

In general yes (there are cases where this is not needed, but let’s
ignore them.)

>> Of these (1) and (3) are currently easy to do on GuixSD.  (Right? :-))
>
> For both (1) and (3), the current GuixSD mechanism appears to require an
> operating system configuration file.

The output of ‘guix system build’ contains the ‘parameters’ file, which
is enough to generate grub.cfg (see ‘previous-grub-entries’ in (guix
scripts system)).

However, the activation script is indeed missing.  We can add it to the
output of ‘guix system build’ by extending ‘system-service-type’:
This way we have direct access to each generation’s activation script
and we should be fine with (3).

WDYT?

> Yes, I think that makes sense.  I need to learn more about GuixSD's
> activation mechanism, but it makes sense that a procedural definition
> (e.g., like in NixOS's switch-to-configuration script) is equivalent to
> a declarative definition.  I think a declarative definition of services
> would be fine.  Concretely speaking, is there a specific format that is
> convenient to use for such a "declarative definition of services"?

I would suggest an sexp as discussed at:

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

> What about the grub installation?

The ‘parameters’ file should be enough, as you wrote.

HTH!

Ludo’.
Chris Marusich - July 25, 2016, 6:22 a.m.
Hi Ludo,

Thank you for the concrete suggestions.  I've looked into using the
parameters file.  It contains almost all the info I need, but I think
some is still missing.

> The output of ‘guix system build’ contains the ‘parameters’ file, which
> is enough to generate grub.cfg (see ‘previous-grub-entries’ in (guix
> scripts system)).

What if someone specifies extra "menu-entries" in their operating system
configuration file?  (as described in "(guix) GRUB Configuration")?
Those extra entries don't appear to be stored in the parameters file.

It would be very convenient if we could just store the entire
<grub-configuration> in the built system output (e.g., the parameters
file).  Is that possible?

> However, the activation script is indeed missing.  We can add it to the
> output of ‘guix system build’ by extending ‘system-service-type’:
>
>
> diff --git a/gnu/services.scm b/gnu/services.scm
> index 5479bfa..fc3e17e 100644
> --- a/gnu/services.scm
> +++ b/gnu/services.scm
> @@ -352,11 +352,18 @@ ACTIVATION-SCRIPT-TYPE."
>  
>  (define (second-argument a b) b)
>  
> +(define (gexps->activation-system-entry gexps)
> +  "Return a directory entry to add to the result of the 'system' derivation."
> +  (mlet %store-monad ((script (activation-script gexps)))
> +    (return `(("activate" ,script)))))
> +
>  (define activation-service-type
>    (service-type (name 'activate)
>                  (extensions
>                   (list (service-extension boot-service-type
> -                                          gexps->activation-gexp)))
> +                                          gexps->activation-gexp)
> +                       (service-extension system-service-type
> +                                          gexps->activation-system-entry)))
>                  (compose append)
>                  (extend second-argument)))
>  
>
>
> This way we have direct access to each generation’s activation script
> and we should be fine with (3).
>
> WDYT?

I'm afraid I don't yet know enough about gexps and the activation
process to give an informed opinion on that suggestion.  After I finish
the first milestone (switch symlinks and rebuild grub.cfg), I'll study
those topics in more detail and revisit your proposal.

Thank you,
Ludovic Courtès - July 25, 2016, 8:06 a.m.
Hi Chris,

Chris Marusich <cmmarusich@gmail.com> skribis:

>> The output of ‘guix system build’ contains the ‘parameters’ file, which
>> is enough to generate grub.cfg (see ‘previous-grub-entries’ in (guix
>> scripts system)).
>
> What if someone specifies extra "menu-entries" in their operating system
> configuration file?  (as described in "(guix) GRUB Configuration")?
> Those extra entries don't appear to be stored in the parameters file.

They’re not stored there, but that’s fine: since there’s only one
grub.cfg, we just store the menu entries that are defined in
‘operating-system’ at the moment ‘guix system reconfigure’ is run.  This
part is “imperative” in nature.

> It would be very convenient if we could just store the entire
> <grub-configuration> in the built system output (e.g., the parameters
> file).  Is that possible?

I don’t think it’s useful because what matters is the
<grub-configuration> that we see in the new operating system.

What do you think?

>> However, the activation script is indeed missing.  We can add it to the
>> output of ‘guix system build’ by extending ‘system-service-type’:

[...]

>> This way we have direct access to each generation’s activation script
>> and we should be fine with (3).
>>
>> WDYT?
>
> I'm afraid I don't yet know enough about gexps and the activation
> process to give an informed opinion on that suggestion.  After I finish
> the first milestone (switch symlinks and rebuild grub.cfg), I'll study
> those topics in more detail and revisit your proposal.

Sure.

Thank you!

Ludo’.

Patch

diff --git a/gnu/services.scm b/gnu/services.scm
index 5479bfa..fc3e17e 100644
--- a/gnu/services.scm
+++ b/gnu/services.scm
@@ -352,11 +352,18 @@  ACTIVATION-SCRIPT-TYPE."
 
 (define (second-argument a b) b)
 
+(define (gexps->activation-system-entry gexps)
+  "Return a directory entry to add to the result of the 'system' derivation."
+  (mlet %store-monad ((script (activation-script gexps)))
+    (return `(("activate" ,script)))))
+
 (define activation-service-type
   (service-type (name 'activate)
                 (extensions
                  (list (service-extension boot-service-type
-                                          gexps->activation-gexp)))
+                                          gexps->activation-gexp)
+                       (service-extension system-service-type
+                                          gexps->activation-system-entry)))
                 (compose append)
                 (extend second-argument)))