Skip to content

Commit

Permalink
Use a shared const and helpers for run/ostree-booted
Browse files Browse the repository at this point in the history
Just a code cleanup.

Closes: containers#934
Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters committed Dec 5, 2024
1 parent 3b9f4e4 commit dfda626
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 43 deletions.
3 changes: 2 additions & 1 deletion lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use fn_error_context::context;
use ostree::gio;
use ostree_container::store::PrepareResult;
use ostree_ext::container as ostree_container;
use ostree_ext::container_utils::is_ostree_booted;
use ostree_ext::keyfileext::KeyFileExt;
use ostree_ext::ostree;
use schemars::schema_for;
Expand Down Expand Up @@ -611,7 +612,7 @@ fn prepare_for_write() -> Result<()> {
if ostree_ext::container_utils::running_in_container() {
anyhow::bail!("Detected container; this command requires a booted host system.");
}
if !std::path::Path::new("/run/ostree-booted").exists() {
if !is_ostree_booted()? {
anyhow::bail!("This command requires an ostree-booted host system");
}
crate::cli::require_root()?;
Expand Down
74 changes: 41 additions & 33 deletions lib/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use anyhow::{Context, Result};
use cap_std::fs::Dir;
use cap_std_ext::{cap_std, dirext::CapStdExtDirExt};
use fn_error_context::context;
use ostree_ext::container_utils::is_ostree_booted_in;
use rustix::{fd::AsFd, fs::StatVfsMountFlags};

const EDIT_UNIT: &str = "bootc-fstab-edit.service";
Expand All @@ -14,7 +15,7 @@ pub(crate) const BOOTC_EDITED_STAMP: &str = "Updated by bootc-fstab-edit.service
#[context("bootc generator")]
pub(crate) fn fstab_generator_impl(root: &Dir, unit_dir: &Dir) -> Result<bool> {
// Do nothing if not ostree-booted
if !root.try_exists("run/ostree-booted")? {
if !is_ostree_booted_in(root)? {
return Ok(false);
}

Expand Down Expand Up @@ -105,31 +106,37 @@ fn test_generator_no_fstab() -> Result<()> {
Ok(())
}

#[test]
fn test_generator_fstab() -> Result<()> {
let tempdir = fixture()?;
let unit_dir = &tempdir.open_dir("run/systemd/system")?;
// Should still be a no-op
tempdir.atomic_write("etc/fstab", "# Some dummy fstab")?;
fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert_eq!(unit_dir.entries()?.count(), 0);

// Also a no-op, not booted via ostree
tempdir.atomic_write("etc/fstab", &format!("# {FSTAB_ANACONDA_STAMP}"))?;
fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert_eq!(unit_dir.entries()?.count(), 0);

// Now it should generate
tempdir.atomic_write("run/ostree-booted", "ostree booted")?;
fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert_eq!(unit_dir.entries()?.count(), 2);

Ok(())
}
#[cfg(test)]
mod test {
use super::*;

use ostree_ext::container_utils::OSTREE_BOOTED;

#[test]
fn test_generator_fstab() -> Result<()> {
let tempdir = fixture()?;
let unit_dir = &tempdir.open_dir("run/systemd/system")?;
// Should still be a no-op
tempdir.atomic_write("etc/fstab", "# Some dummy fstab")?;
fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert_eq!(unit_dir.entries()?.count(), 0);

// Also a no-op, not booted via ostree
tempdir.atomic_write("etc/fstab", &format!("# {FSTAB_ANACONDA_STAMP}"))?;
fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert_eq!(unit_dir.entries()?.count(), 0);

// Now it should generate
tempdir.atomic_write(OSTREE_BOOTED, "ostree booted")?;
fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert_eq!(unit_dir.entries()?.count(), 2);

Ok(())
}

#[test]
fn test_generator_fstab_idempotent() -> Result<()> {
let anaconda_fstab = indoc::indoc! { "
#[test]
fn test_generator_fstab_idempotent() -> Result<()> {
let anaconda_fstab = indoc::indoc! { "
#
# /etc/fstab
# Created by anaconda on Tue Mar 19 12:24:29 2024
Expand All @@ -144,14 +151,15 @@ fn test_generator_fstab_idempotent() -> Result<()> {
UUID=715be2b7-c458-49f2-acec-b2fdb53d9089 / xfs ro 0 0
UUID=341c4712-54e8-4839-8020-d94073b1dc8b /boot xfs defaults 0 0
" };
let tempdir = fixture()?;
let unit_dir = &tempdir.open_dir("run/systemd/system")?;
let tempdir = fixture()?;
let unit_dir = &tempdir.open_dir("run/systemd/system")?;

tempdir.atomic_write("etc/fstab", anaconda_fstab)?;
tempdir.atomic_write("run/ostree-booted", "ostree booted")?;
let updated = fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert!(!updated);
assert_eq!(unit_dir.entries()?.count(), 0);
tempdir.atomic_write("etc/fstab", anaconda_fstab)?;
tempdir.atomic_write(OSTREE_BOOTED, "ostree booted")?;
let updated = fstab_generator_impl(&tempdir, &unit_dir).unwrap();
assert!(!updated);
assert_eq!(unit_dir.entries()?.count(), 0);

Ok(())
Ok(())
}
}
4 changes: 2 additions & 2 deletions lib/src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use std::io::Read;
use std::io::Write;

use anyhow::{Context, Result};
use camino::Utf8Path;
use fn_error_context::context;
use ostree::glib;
use ostree_container::OstreeImageReference;
use ostree_ext::container as ostree_container;
use ostree_ext::container_utils::is_ostree_booted;
use ostree_ext::keyfileext::KeyFileExt;
use ostree_ext::oci_spec;
use ostree_ext::ostree;
Expand Down Expand Up @@ -294,7 +294,7 @@ pub(crate) async fn status(opts: super::cli::StatusOpts) -> Result<()> {
0 | 1 => {}
o => anyhow::bail!("Unsupported format version: {o}"),
};
let host = if !Utf8Path::new("/run/ostree-booted").try_exists()? {
let host = if !is_ostree_booted()? {
Default::default()
} else {
let sysroot = super::cli::get_storage().await?;
Expand Down
27 changes: 22 additions & 5 deletions ostree-ext/src/container_utils.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
//! Helpers for interacting with containers at runtime.
use crate::keyfileext::KeyFileExt;
use anyhow::Result;
use ostree::glib;
use std::io;
use std::io::Read;
use std::path::Path;

use anyhow::Result;
use ocidir::cap_std::fs::Dir;
use ostree::glib;

use crate::keyfileext::KeyFileExt;

/// The relative path to the stamp file which signals this is an ostree-booted system.
pub const OSTREE_BOOTED: &str = "run/ostree-booted";

// See https://github.com/coreos/rpm-ostree/pull/3285#issuecomment-999101477
// For compatibility with older ostree, we stick this in /sysroot where
// it will be ignored.
Expand Down Expand Up @@ -64,6 +71,17 @@ pub fn is_bare_split_xattrs() -> Result<bool> {
}
}

/// Returns true if the system appears to have been booted via ostree.
/// This accesses global state in /run.
pub fn is_ostree_booted() -> io::Result<bool> {
Path::new(&format!("/{OSTREE_BOOTED}")).try_exists()
}

/// Returns true if the target root appears to have been booted via ostree.
pub fn is_ostree_booted_in(rootfs: &Dir) -> io::Result<bool> {
rootfs.try_exists(OSTREE_BOOTED)
}

/// Returns `true` if the current booted filesystem appears to be an ostree-native container.
///
/// This just invokes [`is_bare_split_xattrs`] and [`running_in_container`].
Expand All @@ -73,8 +91,7 @@ pub fn is_ostree_container() -> Result<bool> {
// If we have a container-ostree repo format, then we'll assume we're
// running in a container unless there's strong evidence not (we detect
// we're part of a systemd unit or are in a booted ostree system).
let maybe_container = running_in_container()
|| (!running_in_systemd && !Path::new("/run/ostree-booted").exists());
let maybe_container = running_in_container() || (!running_in_systemd && !is_ostree_booted()?);
Ok(is_container_ostree && maybe_container)
}

Expand Down
4 changes: 2 additions & 2 deletions ostree-ext/src/integrationtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use std::path::Path;

use crate::container_utils::is_ostree_container;
use crate::container_utils::{is_ostree_booted, is_ostree_container};
use anyhow::{anyhow, Context, Result};
use camino::Utf8Path;
use cap_std::fs::Dir;
Expand All @@ -21,7 +21,7 @@ use xshell::cmd;
pub(crate) fn detectenv() -> Result<&'static str> {
let r = if is_ostree_container()? {
"ostree-container"
} else if Path::new("/run/ostree-booted").exists() {
} else if is_ostree_booted()? {
"ostree"
} else if crate::container_utils::running_in_container() {
"container"
Expand Down

0 comments on commit dfda626

Please sign in to comment.