Skip to content

Commit 3c7a2e6

Browse files
cli/composefs: Show staged/rollback deployments
Store the staged deployment at `/run/composefs/staged-deployment` similar to how it's done in ostree Signed-off-by: Pragyan Poudyal <[email protected]>
1 parent 4383a35 commit 3c7a2e6

File tree

3 files changed

+46
-5
lines changed

3 files changed

+46
-5
lines changed

lib/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ async fn upgrade_composefs(_opts: UpgradeOpts) -> Result<()> {
821821
BootType::Uki => setup_composefs_uki_boot(BootSetupType::Upgrade, repo, &id, entry),
822822
}?;
823823

824-
write_composefs_state(&Utf8PathBuf::from("/sysroot"), id, imgref)?;
824+
write_composefs_state(&Utf8PathBuf::from("/sysroot"), id, imgref, true)?;
825825

826826
Ok(())
827827
}

lib/src/install.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub(crate) mod osconfig;
1515

1616
use std::collections::HashMap;
1717
use std::fs::create_dir_all;
18-
use std::io::{Seek, SeekFrom, Write};
18+
use std::io::Write;
1919
use std::os::fd::{AsFd, AsRawFd};
2020
use std::os::unix::fs::symlink;
2121
use std::os::unix::process::CommandExt;
@@ -1781,19 +1781,26 @@ fn setup_composefs_boot(root_setup: &RootSetup, state: &State, image_id: &str) -
17811781
transport: state.source.imageref.transport.to_string(),
17821782
signature: None,
17831783
},
1784+
false,
17841785
)?;
17851786

17861787
Ok(())
17871788
}
17881789

1790+
pub(crate) const COMPOSEFS_TRANSIENT_STATE_DIR: &str = "/run/composefs";
1791+
pub(crate) const COMPOSEFS_STAGED_DEPLOYMENT_PATH: &str = "/run/composefs/staged-deployment";
1792+
/// Relative to /sysroot
1793+
pub(crate) const STATE_DIR_RELATIVE: &str = "state/deploy";
1794+
17891795
/// Creates and populates /sysroot/state/deploy/image_id
17901796
#[context("Writing composefs state")]
17911797
pub(crate) fn write_composefs_state(
17921798
root_path: &Utf8PathBuf,
17931799
deployment_id: Sha256HashValue,
17941800
imgref: &ImageReference,
1801+
staged: bool,
17951802
) -> Result<()> {
1796-
let state_path = root_path.join(format!("state/deploy/{}", deployment_id.to_hex()));
1803+
let state_path = root_path.join(format!("{STATE_DIR_RELATIVE}/{}", deployment_id.to_hex()));
17971804

17981805
create_dir_all(state_path.join("etc/upper"))?;
17991806
create_dir_all(state_path.join("etc/work"))?;
@@ -1823,6 +1830,19 @@ pub(crate) fn write_composefs_state(
18231830
.write(config.to_string().as_bytes())
18241831
.context("Falied to write to .origin file")?;
18251832

1833+
if staged {
1834+
std::fs::create_dir_all(COMPOSEFS_TRANSIENT_STATE_DIR)
1835+
.with_context(|| format!("Creating {COMPOSEFS_TRANSIENT_STATE_DIR}"))?;
1836+
1837+
let mut file = std::fs::OpenOptions::new()
1838+
.write(true)
1839+
.create(true)
1840+
.open(COMPOSEFS_STAGED_DEPLOYMENT_PATH)
1841+
.context("Opening staged-deployment file")?;
1842+
1843+
file.write_all(deployment_id.to_hex().as_bytes())?;
1844+
}
1845+
18261846
Ok(())
18271847
}
18281848

lib/src/status.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use ostree_ext::ostree;
2121
use tokio::io::AsyncReadExt;
2222

2323
use crate::cli::OutputFormat;
24+
use crate::install::{COMPOSEFS_STAGED_DEPLOYMENT_PATH, STATE_DIR_RELATIVE};
2425
use crate::spec::ImageStatus;
2526
use crate::spec::{BootEntry, BootOrder, Host, HostSpec, HostStatus, HostType};
2627
use crate::spec::{ImageReference, ImageSignature};
@@ -389,8 +390,8 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
389390
let sysroot = cap_std::fs::Dir::open_ambient_dir("/sysroot", cap_std::ambient_authority())
390391
.context("Opening sysroot")?;
391392
let deployments = sysroot
392-
.read_dir("state/deploy")
393-
.context("Reading sysroot state/deploy")?;
393+
.read_dir(STATE_DIR_RELATIVE)
394+
.with_context(|| format!("Reading sysroot {STATE_DIR_RELATIVE}"))?;
394395

395396
let host_spec = HostSpec {
396397
image: None,
@@ -399,6 +400,17 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
399400

400401
let mut host = Host::new(host_spec);
401402

403+
let staged_deployment_id = match std::fs::File::open(COMPOSEFS_STAGED_DEPLOYMENT_PATH) {
404+
Ok(mut f) => {
405+
let mut s = String::new();
406+
f.read_to_string(&mut s)?;
407+
408+
Ok(Some(s))
409+
}
410+
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
411+
Err(e) => Err(e),
412+
}?;
413+
402414
for depl in deployments {
403415
let depl = depl?;
404416

@@ -422,6 +434,15 @@ pub(crate) async fn composefs_deployment_status() -> Result<Host> {
422434
host.status.booted = Some(boot_entry);
423435
continue;
424436
}
437+
438+
if let Some(staged_deployment_id) = &staged_deployment_id {
439+
if depl_file_name == staged_deployment_id.trim() {
440+
host.status.staged = Some(boot_entry);
441+
continue;
442+
}
443+
}
444+
445+
host.status.rollback = Some(boot_entry);
425446
}
426447

427448
Ok(host)

0 commit comments

Comments
 (0)