Skip to content

Commit a93e118

Browse files
composefs: Soft Reboot after update/switch if specified
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent 06f9082 commit a93e118

File tree

6 files changed

+91
-17
lines changed

6 files changed

+91
-17
lines changed

crates/lib/src/bootc_composefs/boot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,7 +1268,7 @@ pub(crate) async fn setup_composefs_boot(
12681268

12691269
write_composefs_state(
12701270
&root_setup.physical_root_path,
1271-
id,
1271+
&id,
12721272
&crate::spec::ImageReference::from(state.target_imgref.clone()),
12731273
false,
12741274
boot_type,

crates/lib/src/bootc_composefs/soft_reboot.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,30 @@ use bootc_initramfs_setup::setup_root;
1010
use bootc_kernel_cmdline::utf8::Cmdline;
1111
use bootc_mount::{bind_mount_from_pidns, PID1};
1212
use camino::Utf8Path;
13+
use fn_error_context::context;
14+
use ostree_ext::systemd_has_soft_reboot;
1315
use std::{fs::create_dir_all, os::unix::process::CommandExt, path::PathBuf, process::Command};
1416

1517
const NEXTROOT: &str = "/run/nextroot";
1618

17-
pub(crate) async fn soft_reboot_to_deployment(
19+
/// Checks if the provided deployment is soft reboot capable, and soft reboots the system if
20+
/// argument `reboot` is true
21+
#[context("Soft rebooting")]
22+
pub(crate) async fn prepare_soft_reboot_composefs(
1823
storage: &Storage,
1924
booted_cfs: &BootedComposefs,
2025
deployment_id: &String,
2126
reboot: bool,
2227
) -> Result<()> {
28+
if !systemd_has_soft_reboot() {
29+
anyhow::bail!("System does not support soft reboots")
30+
}
31+
2332
if *deployment_id == *booted_cfs.cmdline.digest {
2433
anyhow::bail!("Cannot soft-reboot to currently booted deployment");
2534
}
2635

36+
// We definitely need to re-query the state as some deployment might've been staged
2737
let host = composefs_deployment_status_from(storage, booted_cfs.cmdline).await?;
2838

2939
let all_deployments = host.all_composefs_deployments()?;

crates/lib/src/bootc_composefs/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ pub(crate) fn update_target_imgref_in_origin(
180180
#[context("Writing composefs state")]
181181
pub(crate) async fn write_composefs_state(
182182
root_path: &Utf8PathBuf,
183-
deployment_id: Sha512HashValue,
183+
deployment_id: &Sha512HashValue,
184184
target_imgref: &ImageReference,
185185
staged: bool,
186186
boot_type: BootType,

crates/lib/src/bootc_composefs/switch.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
bootc_composefs::{
66
state::update_target_imgref_in_origin,
77
status::get_composefs_status,
8-
update::{do_upgrade, is_image_pulled, validate_update, UpdateAction},
8+
update::{do_upgrade, is_image_pulled, validate_update, DoUpgradeOpts, UpdateAction},
99
},
1010
cli::{imgref_for_switch, SwitchOpts},
1111
store::{BootedComposefs, Storage},
@@ -42,6 +42,11 @@ pub(crate) async fn switch_composefs(
4242
let repo = &*booted_cfs.repo;
4343
let (image, img_config) = is_image_pulled(repo, &target_imgref).await?;
4444

45+
let do_upgrade_opts = DoUpgradeOpts {
46+
soft_reboot: opts.soft_reboot,
47+
apply: opts.apply,
48+
};
49+
4550
if let Some(cfg_verity) = image {
4651
let action = validate_update(
4752
storage,
@@ -59,7 +64,15 @@ pub(crate) async fn switch_composefs(
5964
}
6065

6166
UpdateAction::Proceed => {
62-
return do_upgrade(storage, &host, &target_imgref, &img_config).await;
67+
return do_upgrade(
68+
storage,
69+
booted_cfs,
70+
&host,
71+
&target_imgref,
72+
&img_config,
73+
&do_upgrade_opts,
74+
)
75+
.await;
6376
}
6477

6578
UpdateAction::UpdateOrigin => {
@@ -71,7 +84,15 @@ pub(crate) async fn switch_composefs(
7184
}
7285
}
7386

74-
do_upgrade(storage, &host, &target_imgref, &img_config).await?;
87+
do_upgrade(
88+
storage,
89+
booted_cfs,
90+
&host,
91+
&target_imgref,
92+
&img_config,
93+
&do_upgrade_opts,
94+
)
95+
.await?;
7596

7697
Ok(())
7798
}

crates/lib/src/bootc_composefs/update.rs

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@ use crate::{
1515
boot::{setup_composefs_bls_boot, setup_composefs_uki_boot, BootSetupType, BootType},
1616
repo::{get_imgref, pull_composefs_repo},
1717
service::start_finalize_stated_svc,
18+
soft_reboot::prepare_soft_reboot_composefs,
1819
state::write_composefs_state,
1920
status::{
2021
get_bootloader, get_composefs_status, get_container_manifest_and_config, get_imginfo,
2122
ImgConfigManifest,
2223
},
2324
},
24-
cli::UpgradeOpts,
25+
cli::{SoftRebootMode, UpgradeOpts},
2526
composefs_consts::{STATE_DIR_RELATIVE, TYPE1_ENT_PATH_STAGED, USER_CFG_STAGED},
2627
spec::{Bootloader, Host, ImageReference},
2728
store::{BootedComposefs, ComposefsRepository, Storage},
@@ -208,13 +209,21 @@ pub(crate) fn validate_update(
208209
Ok(UpdateAction::Proceed)
209210
}
210211

212+
/// This is just an intersection of SwitchOpts and UpgradeOpts
213+
pub(crate) struct DoUpgradeOpts {
214+
pub(crate) apply: bool,
215+
pub(crate) soft_reboot: Option<SoftRebootMode>,
216+
}
217+
211218
/// Performs the Update or Switch operation
212219
#[context("Performing Upgrade Operation")]
213220
pub(crate) async fn do_upgrade(
214221
storage: &Storage,
222+
booted_cfs: &BootedComposefs,
215223
host: &Host,
216224
imgref: &ImageReference,
217225
img_manifest_config: &ImgConfigManifest,
226+
opts: &DoUpgradeOpts,
218227
) -> Result<()> {
219228
start_finalize_stated_svc()?;
220229

@@ -254,7 +263,7 @@ pub(crate) async fn do_upgrade(
254263

255264
write_composefs_state(
256265
&Utf8PathBuf::from("/sysroot"),
257-
id,
266+
&id,
258267
imgref,
259268
true,
260269
boot_type,
@@ -263,6 +272,14 @@ pub(crate) async fn do_upgrade(
263272
)
264273
.await?;
265274

275+
if opts.apply {
276+
return crate::reboot::reboot();
277+
}
278+
279+
if opts.soft_reboot.is_some() {
280+
prepare_soft_reboot_composefs(storage, booted_cfs, &id.to_hex(), true).await?;
281+
}
282+
266283
Ok(())
267284
}
268285

@@ -299,6 +316,11 @@ pub(crate) async fn upgrade_composefs(
299316
// Or if we have another staged deployment with a different image
300317
let staged_image = host.status.staged.as_ref().and_then(|i| i.image.as_ref());
301318

319+
let do_upgrade_opts = DoUpgradeOpts {
320+
soft_reboot: opts.soft_reboot,
321+
apply: opts.apply,
322+
};
323+
302324
if let Some(staged_image) = staged_image {
303325
// We have a staged image and it has the same digest as the currently booted image's latest
304326
// digest
@@ -337,7 +359,15 @@ pub(crate) async fn upgrade_composefs(
337359
}
338360

339361
UpdateAction::Proceed => {
340-
return do_upgrade(storage, &host, booted_imgref, &img_config).await;
362+
return do_upgrade(
363+
storage,
364+
composefs,
365+
&host,
366+
booted_imgref,
367+
&img_config,
368+
&do_upgrade_opts,
369+
)
370+
.await;
341371
}
342372

343373
UpdateAction::UpdateOrigin => {
@@ -365,7 +395,15 @@ pub(crate) async fn upgrade_composefs(
365395
}
366396

367397
UpdateAction::Proceed => {
368-
return do_upgrade(storage, &host, booted_imgref, &img_config).await;
398+
return do_upgrade(
399+
storage,
400+
composefs,
401+
&host,
402+
booted_imgref,
403+
&img_config,
404+
&do_upgrade_opts,
405+
)
406+
.await;
369407
}
370408

371409
UpdateAction::UpdateOrigin => {
@@ -382,11 +420,15 @@ pub(crate) async fn upgrade_composefs(
382420
return Ok(());
383421
}
384422

385-
do_upgrade(storage, &host, booted_imgref, &img_config).await?;
386-
387-
if opts.apply {
388-
return crate::reboot::reboot();
389-
}
423+
do_upgrade(
424+
storage,
425+
composefs,
426+
&host,
427+
booted_imgref,
428+
&img_config,
429+
&do_upgrade_opts,
430+
)
431+
.await?;
390432

391433
Ok(())
392434
}

crates/lib/src/cli.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use serde::{Deserialize, Serialize};
3535
use tempfile::tempdir_in;
3636

3737
use crate::bootc_composefs::delete::delete_composefs_deployment;
38-
use crate::bootc_composefs::soft_reboot::soft_reboot_to_deployment;
38+
use crate::bootc_composefs::soft_reboot::prepare_soft_reboot_composefs;
3939
use crate::bootc_composefs::{
4040
finalize::{composefs_backend_finalize, get_etc_diff},
4141
rollback::composefs_rollback,
@@ -1779,7 +1779,8 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
17791779
anyhow::bail!("soft-reboot only implemented for composefs")
17801780
}
17811781
BootedStorageKind::Composefs(booted_cfs) => {
1782-
soft_reboot_to_deployment(&storage, &booted_cfs, &deployment, reboot).await
1782+
prepare_soft_reboot_composefs(&storage, &booted_cfs, &deployment, reboot)
1783+
.await
17831784
}
17841785
}
17851786
}

0 commit comments

Comments
 (0)