Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos:nixos-rebuild: allow switching to a specific generation number #105910

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

miallo
Copy link
Contributor

@miallo miallo commented Dec 4, 2020

Motivation for this change

If the user wants to rollback to any of the system generations but the last, this is currently not easily doable (see #24374).
In order to unify the interface with nix-env a bit more, I propose to add a flag ``nixos-rebuild --generation` to easily go to a specific generation.

I had an issue, where I didn't notice a package breaking ~10 generations ago and while fixing it, I had to go back and forth multiple times. Since I didn't know about

sudo nix-env --switch-generation 12345 -p /nix/var/nix/profiles/system
sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch

I repeated the rollback n times.

This implementation would make it possible to run

sudo nixos-rebuild switch --generation 12345
Maintainers

@nbp added --rollback
@worldofpeace did the last edits
And I guess @edolstra ?

Things done
  • Tested manually on local system
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

@miallo miallo changed the title WIP Allow nixos-rebuild --switch-generation WIP: Allow nixos-rebuild --switch-generation Dec 4, 2020
@miallo miallo changed the title WIP: Allow nixos-rebuild --switch-generation nixos:nixos-rebuild: [WIP] Allow nixos-rebuild --switch-generation Dec 4, 2020
@miallo miallo changed the title nixos:nixos-rebuild: [WIP] Allow nixos-rebuild --switch-generation nixos:nixos-rebuild: Allow nixos-rebuild --switch-generation Dec 5, 2020
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/prs-ready-for-review/3032/394

@miallo miallo changed the title nixos:nixos-rebuild: Allow nixos-rebuild --switch-generation nixos:nixos-rebuild: Add --switch-generation flag Dec 12, 2020
@miallo
Copy link
Contributor Author

miallo commented Jan 3, 2021

I am not sure about having list-generations in nixos-rebuild, because it isn't strictly related to rebuilding. But on the other hand, having a seperate nixos-list-generations command feels a bit overkill as well, looking at the short list of existing nixos-* commands... On the other hand one could add parameters for formatting and so on, but I am not sure if that is really needed...

Any opinions @edolstra or others?

@miallo
Copy link
Contributor Author

miallo commented Jan 3, 2021

Many ideas for the list-generations come from the script that builds the grub-menu. Maybe it would be worth, having one script that produces a description for a given generation so that grub, as well as the list-generations can utilize it?

@edolstra
Copy link
Member

edolstra commented Jan 4, 2021

Maybe this should be its own subcommand? I.e. nixos-rebuild switch-generation rather than switch --switch-generation, which seems a bit superfluous.

Or alternatively, nixos-rebuild [switch|test] --generation.

@miallo miallo changed the title nixos:nixos-rebuild: Add --switch-generation flag nixos:nixos-rebuild: Add --generation flag Jan 4, 2021
@miallo
Copy link
Contributor Author

miallo commented Jan 4, 2021

I totally agree with your suggestions and I was a bit unhappy with the doubling of the "switch" as well. The reason I chose it nevertheless is that I took the same flag as nix-env...
So far I only used switch and I don't know if others would want to test old generations. But given the fact that --rollback supports both, I guess having a similar interface would be good. I think the nixos-rebuild [switch|test] --generation sounds nice.

@miallo
Copy link
Contributor Author

miallo commented Jan 4, 2021

Any opinions about the list-generations subcommand? I added it to this PR, because with the option to switch to a specific generation I thought it would be nice to have an overview about the main things. I guess a (current) tag as in nix-env --list-generations might be usefull as well.

@edolstra
Copy link
Member

edolstra commented Jan 4, 2021

I think it's okay to add it to nixos-rebuild for now. There is an issue somewhere about replacing nixos-rebuild with a nixos command that would resolve the fact that it's not related to building.

@miallo
Copy link
Contributor Author

miallo commented Jan 6, 2021

I prepared a branch with two clean commits instead of this mess and I could use those instead. I guess it would be easier to read that way

@miallo miallo force-pushed the nixos-rebuild/switch-generation branch from 5e37822 to dc528f0 Compare January 7, 2021 22:51
@miallo miallo force-pushed the nixos-rebuild/switch-generation branch from dc528f0 to 3073ca2 Compare January 15, 2021 07:59
@miallo
Copy link
Contributor Author

miallo commented Jan 15, 2021

Anyone wants to take a look and review this?

@miallo miallo force-pushed the nixos-rebuild/switch-generation branch from 1ab9cab to a0e6d87 Compare January 16, 2021 14:36
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/prs-ready-for-review/3032/2687

@mairs8
Copy link

mairs8 commented Nov 4, 2023

i thought that switching to specific generation is acheived by: /nix/var/nix/profiles/system-N-link/bin/switch-to-configuration switch where N is the generation to switch to.

Is this thread about adding a more convenient syntax, for example to switch to generation 5: nixos-rebuild switch --rollback 5 ?

@miallo
Copy link
Contributor Author

miallo commented Nov 5, 2023

i thought that switching to specific generation is acheived by: /nix/var/nix/profiles/system-N-link/bin/switch-to-configuration switch where N is the generation to switch to.

Yes, I think so. This PR is equivalent to

sudo nix-env --switch-generation N -p /nix/var/nix/profiles/system
sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch

because that is also the way it was implemented for --rollback. I am not 100% sure about the implications - it might just be the use of a couple of programs from the later (potentially broken) generation if I am not mistaken. But maybe this is indeed just too complex for this and the reason it was used for --rollback was not to duplicate the logic of "How to find the previous generation?" in nixos-rebuild and nix-env 🤔 Someone with a better understanding of the details should probably take a close look at it...

Is this thread about adding a more convenient syntax

Yes, I think having an easier syntax would be better than the current way (and also more discoverable, especially as soon as you add things like different profiles/specialisations).

for example to switch to generation 5: nixos-rebuild switch --rollback 5 ?

I considered your suggested syntax, but I think it is a bit ambiguous if you want to rollback to a specific generation (as is the intention here) or a relative amount (so in your case e.g. from generation 100 to 95). That is why I thought a different syntax is more precise and it is also the one Eelco suggested: #105910 (comment)

Copy link
Contributor

@bzm3r bzm3r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything here makes sense/looks good to me. I too would be interested in helping @miallo pushing this forward.

@miallo miallo force-pushed the nixos-rebuild/switch-generation branch from ac807ee to c3ddde6 Compare November 19, 2023 19:26
@miallo
Copy link
Contributor Author

miallo commented Nov 19, 2023

Everything here makes sense/looks good to me. I too would be interested in helping @miallo pushing this forward.

That would be nice!

I just pushed a rebase where the only change I made was the update of the nixos-rebuild list-generations output in nixos/doc/manual/administration/rollback.section.md since the format has changed between when I implemented it and wrote this doc and now...

@ThinkChaos
Copy link
Contributor

I'd love to see this merged, the current manpage mentions switch --generation n which is not yet available so the situation is quite confusing!

@miallo
Copy link
Contributor Author

miallo commented Nov 27, 2023

the current manpage mentions switch --generation n which is not yet available so the situation is quite confusing!

Oh damn... -.- That one is totally on me. I extracted the list-generations feature into a separate MR and even though I was certain that I fixed the man-page in that MR at some point not to include that reference I must have messed it up...
I don't have a clue on how to push this MR, so in order to avoid confusion I'll remove that sentence in a different MR...

miallo added a commit to miallo/nixpkgs that referenced this pull request Nov 27, 2023
This is a hint that mentions the feature NixOS#105910 but that is not yet
merged. This is very confusing and since it there is no progress with
that merge we should remove the reference
miallo and others added 2 commits December 4, 2023 15:56
Run `nixos-rebuild switch --generation 12345` to roll back to generation
`12345`. This makes rolling back to an older generation easier

Also updated the release notes.
@miallo miallo force-pushed the nixos-rebuild/switch-generation branch from f096884 to 8414cdd Compare December 4, 2023 14:57
@miallo
Copy link
Contributor Author

miallo commented Dec 4, 2023

I just added some tests. This was the first time I wrote any nixos tests and so this is just an adaptation of tests/nixos-rebuild-specialisations.nix - but I don't really know if this can be simplified any more...

@Mic92 @SuperSandro2000 What else do you think is necessary for this PR?

@SuperSandro2000 you mentioned a few things you wanted to do in #105910 (review)

Copy link
Member

@SuperSandro2000 SuperSandro2000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets only use one style of test at least in the changed code

pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh Outdated Show resolved Hide resolved
pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh Outdated Show resolved Hide resolved
Previously there was a mixture of `[` and `[[`. That is a bit unnecessary and even if there is a mixture in the rest of the code, this PR should stick to one of the versions...

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
--generation)
if [ $# -eq 0 ]; then
log "Must provide a generation number"
log "Usage: \`$(basename "$0") ${action:-switch} --generation <NUMBER>'"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do I need to give an action when I just want to switch to a generation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't know if you want to switch, boot or test said generation, so you have to tell us what you want to do with it...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but if I want to switch to an older generation, why does it start to build the current config file from disk which might be newer than the current generation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is interesting - I don't think this happened to me before 🤔 Where did you see this behavior? If it is in the tests: the first three tests don't actually do the --generation, but they create the generations, so there it is expected that they build the config files...

I know it isn't a good answer, but: I don't really know what I am doing (at least not 3 years after I first wrote this patch). I just adapted the code for the --rollback since I thought they would be more or less identical... I have forgotten the few things I knew about the nix-env stuff and the rest on how this is activated 🙈 If we just wanted to activate the generation and don't care about the action I guess we could also just run /nix/var/nix/profiles/system-$generation-link/activate...

I tried to add a test for the boot --generation, but something is strange (maybe the QEMU runs some kind of tempfs - at least after the machine.reboot() and it doesn't have nix-channels or actually the old generations any more on the disk) and so I could only check that the current generation was still active...

Copy link
Contributor Author

@miallo miallo Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not reproduce the building of the current configuration.nix in the tests, as this passes, which I think is what you mean:

diff --git a/nixos/tests/nixos-rebuild-switch.nix b/nixos/tests/nixos-rebuild-switch.nix
index b9ed2954299a..e5f3e378ad73 100644
--- a/nixos/tests/nixos-rebuild-switch.nix
+++ b/nixos/tests/nixos-rebuild-switch.nix
@@ -84,12 +84,15 @@ import ./make-test-python.nix ({ pkgs, ... }: {

       with subtest("Create generation 3"):
           ${createConfig "3"}
-          machine.succeed("nixos-rebuild switch")
+          out = machine.succeed("nixos-rebuild switch 2>&1")
+          assert "building the system configuration..." in out
           ${testForBootGeneration "3"}
           ${testForActiveGeneration "3"}

       with subtest("must switch to `--generation 1`"):
-          machine.succeed("nixos-rebuild switch --generation 1")
+          ${createConfig "4"}
+          out = machine.succeed("nixos-rebuild switch --generation 1 2>&1")
+          assert "building the system configuration..." not in out
           ${testForBootGeneration "1"}
           ${testForActiveGeneration "1"}

Did I misunderstand you or do you have a reproduction by any chance?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we just wanted to activate the generation and don't care about the action I guess we could also just run /nix/var/nix/profiles/system-$generation-link/activate...

Yes, this is basically what I wanted to do.

Did I misunderstand you or do you have a reproduction by any chance?

I think this is what I did, yes.

well the script (re)executes itself

I am usually passing --fast to it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we just wanted to activate the generation and don't care about the action I guess we could also just run /nix/var/nix/profiles/system-$generation-link/activate...

Yes, this is basically what I wanted to do.

I just implemented it with "feature parity" to the --rollback. I personally mostly use switch as an action, but maybe e.g. someone could want to set a "known good generation" as a default after a reboot when testing a server update and on error they can just do a reboot and everything should be back to normal. Could something like this be a use case (and if not, just out of curiosity: why would it be one for rollback)?

Did I misunderstand you or do you have a reproduction by any chance?

I think this is what I did, yes.

Very interesting... This should not happen (https://github.com/NixOS/nixpkgs/pull/105910/files#diff-fc23c722779993fcffc932965cd143b265aa196d577ca10173b63e5bdcbc0001R608-R609) and also the test that I wrote above passes... 🤔 I really don't have a clue how this could have happened... Anyone has any idea (or even better can add a failing test case)?

@theduke

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

None yet