Skip to content

Commit 45d51d9

Browse files
composefs: Soft Reboot after update/switch if specified
Signed-off-by: Pragyan Poudyal <[email protected]>
1 parent d1b02a4 commit 45d51d9

File tree

6 files changed

+54
-17
lines changed

6 files changed

+54
-17
lines changed

crates/lib/src/bootc_composefs/boot.rs

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

12131213
write_composefs_state(
12141214
&root_setup.physical_root_path,
1215-
id,
1215+
&id,
12161216
&crate::spec::ImageReference::from(state.target_imgref.clone()),
12171217
false,
12181218
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
@@ -155,7 +155,7 @@ pub(crate) fn update_target_imgref_in_origin(
155155
#[context("Writing composefs state")]
156156
pub(crate) fn write_composefs_state(
157157
root_path: &Utf8PathBuf,
158-
deployment_id: Sha512HashValue,
158+
deployment_id: &Sha512HashValue,
159159
imgref: &ImageReference,
160160
staged: bool,
161161
boot_type: BootType,

crates/lib/src/bootc_composefs/switch.rs

Lines changed: 9 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, manifest, _) = 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,8 @@ pub(crate) async fn switch_composefs(
5964
}
6065

6166
UpdateAction::Proceed => {
62-
return do_upgrade(storage, &host, &target_imgref).await;
67+
return do_upgrade(storage, booted_cfs, &host, &target_imgref, &do_upgrade_opts)
68+
.await;
6369
}
6470

6571
UpdateAction::UpdateOrigin => {
@@ -71,7 +77,7 @@ pub(crate) async fn switch_composefs(
7177
}
7278
}
7379

74-
do_upgrade(storage, &host, &target_imgref).await?;
80+
do_upgrade(storage, booted_cfs, &host, &target_imgref, &do_upgrade_opts).await?;
7581

7682
Ok(())
7783
}

crates/lib/src/bootc_composefs/update.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ 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::{get_bootloader, get_composefs_status, get_container_manifest_and_config},
2021
},
21-
cli::UpgradeOpts,
22+
cli::{SoftRebootMode, UpgradeOpts},
2223
composefs_consts::{STATE_DIR_RELATIVE, TYPE1_ENT_PATH_STAGED, USER_CFG_STAGED},
2324
spec::{Bootloader, Host, ImageReference},
2425
store::{BootedComposefs, ComposefsRepository, Storage},
@@ -205,12 +206,20 @@ pub(crate) fn validate_update(
205206
Ok(UpdateAction::Proceed)
206207
}
207208

209+
/// This is just an intersection of SwitchOpts and UpgradeOpts
210+
pub(crate) struct DoUpgradeOpts {
211+
pub(crate) apply: bool,
212+
pub(crate) soft_reboot: Option<SoftRebootMode>,
213+
}
214+
208215
/// Performs the Update or Switch operation
209216
#[context("Performing Upgrade Operation")]
210217
pub(crate) async fn do_upgrade(
211218
storage: &Storage,
219+
booted_cfs: &BootedComposefs,
212220
host: &Host,
213221
imgref: &ImageReference,
222+
opts: &DoUpgradeOpts,
214223
) -> Result<()> {
215224
start_finalize_stated_svc()?;
216225

@@ -250,13 +259,21 @@ pub(crate) async fn do_upgrade(
250259

251260
write_composefs_state(
252261
&Utf8PathBuf::from("/sysroot"),
253-
id,
262+
&id,
254263
imgref,
255264
true,
256265
boot_type,
257266
boot_digest,
258267
)?;
259268

269+
if opts.apply {
270+
return crate::reboot::reboot();
271+
}
272+
273+
if opts.soft_reboot.is_some() {
274+
prepare_soft_reboot_composefs(storage, booted_cfs, &id.to_hex(), true).await?;
275+
}
276+
260277
Ok(())
261278
}
262279

@@ -285,6 +302,11 @@ pub(crate) async fn upgrade_composefs(
285302
// Or if we have another staged deployment with a different image
286303
let staged_image = host.status.staged.as_ref().and_then(|i| i.image.as_ref());
287304

305+
let do_upgrade_opts = DoUpgradeOpts {
306+
soft_reboot: opts.soft_reboot,
307+
apply: opts.apply,
308+
};
309+
288310
if let Some(staged_image) = staged_image {
289311
// We have a staged image and it has the same digest as the currently booted image's latest
290312
// digest
@@ -325,7 +347,8 @@ pub(crate) async fn upgrade_composefs(
325347
}
326348

327349
UpdateAction::Proceed => {
328-
return do_upgrade(storage, &host, booted_imgref).await;
350+
return do_upgrade(storage, composefs, &host, booted_imgref, &do_upgrade_opts)
351+
.await;
329352
}
330353

331354
UpdateAction::UpdateOrigin => {
@@ -353,7 +376,8 @@ pub(crate) async fn upgrade_composefs(
353376
}
354377

355378
UpdateAction::Proceed => {
356-
return do_upgrade(storage, &host, booted_imgref).await;
379+
return do_upgrade(storage, composefs, &host, booted_imgref, &do_upgrade_opts)
380+
.await;
357381
}
358382

359383
UpdateAction::UpdateOrigin => {
@@ -390,11 +414,7 @@ pub(crate) async fn upgrade_composefs(
390414
return Ok(());
391415
}
392416

393-
do_upgrade(storage, &host, booted_imgref).await?;
394-
395-
if opts.apply {
396-
return crate::reboot::reboot();
397-
}
417+
do_upgrade(storage, composefs, &host, booted_imgref, &do_upgrade_opts).await?;
398418

399419
Ok(())
400420
}

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,
@@ -1651,7 +1651,8 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
16511651
anyhow::bail!("soft-reboot only implemented for composefs")
16521652
}
16531653
BootedStorageKind::Composefs(booted_cfs) => {
1654-
soft_reboot_to_deployment(&storage, &booted_cfs, &deployment, reboot).await
1654+
prepare_soft_reboot_composefs(&storage, &booted_cfs, &deployment, reboot)
1655+
.await
16551656
}
16561657
}
16571658
}

0 commit comments

Comments
 (0)