-
Notifications
You must be signed in to change notification settings - Fork 28
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
Import GRUB static migration code #790
base: main
Are you sure you want to change the base?
Conversation
Skipping CI for Draft Pull Request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this!
src/bootupd.rs
Outdated
@@ -489,6 +496,88 @@ pub(crate) fn client_run_validate() -> Result<()> { | |||
Ok(()) | |||
} | |||
|
|||
pub(crate) fn client_run_migrate() -> Result<()> { | |||
// Used to condition execution of this unit at the systemd level | |||
let stamp_file="/var/lib/.fedora_atomic_desktops_static_grub"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing a cargo fmt
.
Also... now that this is part of bootupd calling the stamp file name "fedora_atomic_desktops_" seems odd.
Bikeshedding things a bit more...bootupd already has its own little database where we could store this state.
I'm also fine just keeping it as a stamp file, but how about e.g. .bootupd-static-migration-complete
? Also since this is about data in /boot
I think we should probably keep the stamp file there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to have this represented in bootup state directly then we would have to add a new mode to distinguish between the bootupd managed static grub configs and the ones that we imported from a system that are still user managed because they may contain arbitrary changes, os-prober systems, etc. and we don't want bootupd to override those on static config updates (when we'll implement that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm...I more meant that we add a new key to the JSON file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in the end, I have not done that yet as:
- I would have to figure out how to do it and test it
- Having a stamp file makes it easy to skip running this later during boot using systemd
I immediately ran into fedora-selinux/selinux-policy#2444 while testing this. |
0436363
to
ed15ca7
Compare
Overall LGTM, I can help to do some testing if you have some instructions. |
How I'm (manually) testing this change:
|
ec3c25f
to
e17023d
Compare
So this works as far as I've tested but we have no tests for it yet. |
Do testing on BIOS VM and UEFI VM, then upgrade to f41, copy the new |
e17023d
to
4a65f3b
Compare
Documentation=https://github.com/coreos/bootupd | ||
ConditionPathExists=!/boot/.bootupd-static-migration-complete | ||
RequiresMountsFor=/sysroot /boot | ||
# Only run after a successful bootloader update |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any systems which would enable the static migration but not the update service?
If not, why wouldn't we just fold this functionality into the bootloader-update.service
via
ExecStart=bootupctl migrate
ExecStart=bootupctl update
Or I guess just have bootupctl update --migrate-if-needed
or so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We indeed want all the systems that do the migration to update their bootloader before.
We don't need to do the migration on systems which already have a static GRUB configs and we can check the state for that, so maybe this should indeed be folded into a single command and moved from a stamp file to a field in the state JSON.
If we merge both units then it also means that we have to careful when rolling this out as we won't be easily able to enable one or the other independently. But that's also kind of OK as I'm looking at doing that in F41 as well before the F42 release.
Note that the service is intentionally not enabled by default as it should be up to the distribution to add a systemd preset if the migration to a static GRUB config is needed. This will be used on Atomic Desktops & IoT systems to migrate systems to a static GRUB config before enabling composefs as GRUB curently does not interact well with it: https://bugzilla.redhat.com/show_bug.cgi?id=2308594 See: coreos#789 See: https://fedoraproject.org/wiki/Changes/ComposefsAtomicDesktops
4a65f3b
to
06132d0
Compare
Ask a silly question, is there any reason should do the migration only when Check on silverblue40 (using efi), it is symlink to |
As far I know, this is the marker that lets us tell a system with a dynamic config from one with a static one.
On Silverblue 40, GRUB is setup using a dynamic config like package mode Fedora and on Silverblue 41, it is setup by bootupd with a static config. |
@@ -58,6 +58,8 @@ pub enum CtlVerb { | |||
AdoptAndUpdate, | |||
#[clap(name = "validate", about = "Validate system state")] | |||
Validate, | |||
#[clap(name = "migrate", about = "Migrate a system to static a GRUB config")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Migrate is a bit generic, should this be migrate-grub ?
#[clap(name = "migrate", about = "Migrate a system to static a GRUB config")] | |
#[clap(name = "migrate-grub", about = "Migrate a system to a static GRUB config")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll do that.
.context("Failed to exchange symlink with current GRUB config")?; | ||
|
||
// Remove the now unused symlink (optional cleanup, ignore any failures) | ||
_ = dirfd.remove_file("grub.cfg.current"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also delete the target of the symlink (/boot/loader/grub.cfg
) ?
It'll be delete on the next ostree deploy, but it's cleaner IMO.
Or we could just mv $(readlink -ne /boot/grub2/grub.cfg) /boot/grub2/grub.cfg
I would also add a sync
call after the mv
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also delete the target of the symlink (
/boot/loader/grub.cfg
) ?
It'll be delete on the next ostree deploy, but it's cleaner IMO.
We could, but it's harmless and as you said it will be "removed" (not generated) for the next deployment. Keeping it makes things easier for debugging for now.
Or we could just
mv $(readlink -ne /boot/grub2/grub.cfg) /boot/grub2/grub.cfg
AFAIK that would not be atomic.
I would also add a
sync
call after themv
We should indeed do that. I'll add this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK that would not be atomic.
both files are under a single fs /boot so I don't see why it would not be atomic
[Unit] | ||
Description=bootupd static GRUB config migration | ||
Documentation=https://github.com/coreos/bootupd | ||
ConditionPathExists=!/boot/.bootupd-static-migration-complete |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't want to leave another stamp file around we can use
ConditionPathExists=!/boot/.bootupd-static-migration-complete | |
ConditionPathIsSymbolicLink=/etc/grub2/grub.cfg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's /boot/grub2/grub.cfg
that is a symlink but we can not do that as this would skip all the logic after the symlink change that is still needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I meant /boot/grub2/grub.cfg
not /etc/grub2/grub.cfg
...)
Indeed it's not good if we get interrupted
// Migration complete, let's write the stamp file | ||
File::create(stamp_file)?; | ||
|
||
println!("Static GRUB config migration completed successfully!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the end this script doesn't switch to static config ("static-configs":null
), it just ensure we are properly switched to a BLS compatible config (really old grub or if we had ostree-grub2)
Also grub2-mkconfig
will actually still use grub2-probe
(os-prober
) and fail with composefs enabled,
so we can't update + migrate + enable composefs in a single update (my use case is offline appliances, possibly skipping updates).
Shouldn't we switch to static config generated by bootupd (same as during install) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the end this script doesn't switch to static config (
"static-configs":null
), it just ensure we are properly switched to a BLS compatible config (really old grub or if we had ostree-grub2)
It does switch the system to a static GRUB config that is no longer updated on deployment changes. What it does not do is use the static config from bootupd, to preseve changes that users may have done in their existing configs. Thus we can not record those in the static-configs entry in the state JSON as those are not the same configs.
Also
grub2-mkconfig
will actually still usegrub2-probe
(os-prober
) and fail with composefs enabled, so we can't update + migrate + enable composefs in a single update (my use case is offline appliances, possibly skipping updates).
Indeed, this is why I'm looking at pushing that to Fedora 41 as well, before the F42 release. I'll have to investigate that more.
Shouldn't we switch to static config generated by bootupd (same as during install) ?
We can not do that as that would remove local user config customisations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we switch to static config generated by bootupd (same as during install) ?
We can not do that as that would remove local user config customisations.
With your Fedora hat it makes sense to be cautious, but for the appliance use case I would really like to be able to just remove grub-tools completely and have bootupd adopt grub.cfg as well, so there is no drift between an upgraded system and a fresh install
I'm tempted to just run
rm /boot/bootupd-state.json
bootupctl backend install --auto --write-uuid /
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I want #578
Thinking about this more, this means that we can not take the approach as written in this current PR as the grub configuration generation would fail as part of the generation on the first boot on F42 with composefs enabled. We have multiple options:
|
Fixes: #789