diff --git a/lib/src/image.rs b/lib/src/image.rs index 18b3e606..ebd92756 100644 --- a/lib/src/image.rs +++ b/lib/src/image.rs @@ -14,6 +14,7 @@ use serde::Serialize; use crate::{ boundimage::query_bound_images, cli::{ImageListFormat, ImageListType}, + imgstorage::ensure_floating_c_storage_initialized, }; /// The name of the image we push to containers-storage if nothing is specified. @@ -138,6 +139,7 @@ pub(crate) async fn push_entrypoint(source: Option<&str>, target: Option<&str>) name: target.to_owned(), } } else { + ensure_floating_c_storage_initialized(); ImageReference { transport: Transport::ContainerStorage, name: IMAGE_DEFAULT.to_string(), diff --git a/lib/src/imgstorage.rs b/lib/src/imgstorage.rs index 0fe01f6f..796c03f6 100644 --- a/lib/src/imgstorage.rs +++ b/lib/src/imgstorage.rs @@ -119,6 +119,31 @@ fn new_podman_cmd_in(storage_root: &Dir, run_root: &Dir) -> Result { Ok(cmd) } +/// Ensure that "podman" is the first thing to touch the global storage +/// instance. This is a workaround for https://github.com/containers/bootc/pull/1101#issuecomment-2653862974 +/// Basically podman has special upgrade logic for when it is the first thing +/// to initialize the c/storage instance it sets the networking to netavark. +/// If it's not the first thing, then it assumes an upgrade scenario and we +/// may be using CNI. +/// +/// But this legacy path is triggered through us using skopeo, turning off netavark +/// by default. Work around this by ensuring that /usr/bin/podman is +/// always the first thing to touch c/storage (at least, when invoked by us). +/// +/// Call this function any time we're going to write to containers-storage. +pub(crate) fn ensure_floating_c_storage_initialized() { + if let Err(e) = Command::new("podman") + .args(["system", "info"]) + .stdout(Stdio::null()) + .run() + { + // Out of conservatism we don't make this operation fatal right now. + // If something went wrong, then we'll probably fail on a later operation + // anyways. + tracing::warn!("Failed to query podman system info: {e}"); + } +} + impl Storage { /// Create a `podman image` Command instance prepared to operate on our alternative /// root. diff --git a/tests/booted/test-image-pushpull-upgrade.nu b/tests/booted/test-image-pushpull-upgrade.nu index 969b9a01..bb1b9941 100644 --- a/tests/booted/test-image-pushpull-upgrade.nu +++ b/tests/booted/test-image-pushpull-upgrade.nu @@ -31,10 +31,6 @@ def initial_build [] { let td = mktemp -d cd $td - # Work around https://github.com/containers/bootc/pull/1101#issuecomment-2653862974 - # Basically things break unless "podman" initializes the c/storage instance right now. - podman images -q o>/dev/null - bootc image copy-to-storage let img = podman image inspect localhost/bootc | from json diff --git a/tests/booted/test-logically-bound-switch.nu b/tests/booted/test-logically-bound-switch.nu index 6ca5650c..f1846a7a 100644 --- a/tests/booted/test-logically-bound-switch.nu +++ b/tests/booted/test-logically-bound-switch.nu @@ -17,9 +17,6 @@ let st = bootc status --json | from json let booted = $st.status.booted.image def initial_setup [] { - # Work around https://github.com/containers/bootc/pull/1101#issuecomment-2653862974 - # Basically things break unless "podman" initializes the c/storage instance right now. - podman images -q o>/dev/null bootc image copy-to-storage podman images podman image inspect localhost/bootc | from json