Repository navigation
to-disk: Switch to a minimal boot target for to-disk installation #370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Test fixture: Bootc image with a quadlet that starts at boot | ||
| # | ||
| # This creates an image with an example service that starts at boot | ||
| # at the default.target that would normally break the bootc to-disk process. | ||
| # We use this test to confirm that we are booting into our custom target | ||
| # where only required services are started. | ||
| # | ||
| # Usage: | ||
| # podman build -f Dockerfile.quadlet -t localhost/bcvk-test-quadlet:latest \ | ||
| # --build-arg BASE_IMAGE=quay.io/centos-bootc/centos-bootc:stream10 . | ||
|
|
||
| ARG BASE_IMAGE=quay.io/centos-bootc/centos-bootc:stream10 | ||
|
|
||
| FROM ${BASE_IMAGE} | ||
|
|
||
| COPY --chown=0:0 <<EOF /etc/containers/systemd/sleep.container | ||
| [Container] | ||
| Image=docker.io/library/alpine:latest | ||
| Exec=sleep 600 | ||
|
|
||
| [Install] | ||
| # Triggers the container to start automatically when the system boots normally | ||
| WantedBy=default.target | ||
| EOF | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,6 +86,7 @@ use color_eyre::eyre::{eyre, Context}; | |
| use color_eyre::Result; | ||
| use indicatif::HumanDuration; | ||
| use indoc::indoc; | ||
| use tempfile::TempDir; | ||
| use tracing::debug; | ||
|
|
||
| /// Supported disk image formats | ||
|
|
@@ -528,11 +529,26 @@ pub fn run(mut opts: ToDiskOpts) -> Result<RunOutcome> { | |
|
|
||
| let tty = std::io::stdout().is_terminal(); | ||
|
|
||
| // Boot the install VM to a minimal target instead of default.target. | ||
| // This is to prevent user-created services in the image (such as quadlets) | ||
| // from interfering with the to-disk install process. | ||
| // | ||
| // bcvk-to-disk.target starts only what the install needs: | ||
| // basic.target, network-online + sshd (the host drives | ||
| // the install over SSH), and remote-fs (virtiofs host-storage mounts). | ||
| let units_dir = TempDir::new()?; | ||
| let units_system_dir = units_dir.path().join("system"); | ||
| std::fs::create_dir_all(&units_system_dir)?; | ||
| std::fs::write( | ||
| units_system_dir.join("bcvk-to-disk.target"), | ||
| include_str!("units/bcvk-to-disk.target"), | ||
| )?; | ||
|
|
||
| // Configure VM for installation: | ||
| // - Use source image as installer environment | ||
| // - Mount host storage read-only for image access | ||
| // - Attach target disk via virtio-blk | ||
| // - Disable networking (using local storage only) | ||
| // - Boot to bcvk-to-disk.target instead of default.target | ||
| let ephemeral_opts = RunEphemeralOpts { | ||
| host_dns_servers: None, | ||
| image: opts.get_installer_image().to_string(), | ||
|
|
@@ -550,14 +566,14 @@ pub fn run(mut opts: ToDiskOpts) -> Result<RunOutcome> { | |
| add_swap: Some(format!("{disk_size}")), | ||
| bind_mounts: Vec::new(), // No additional bind mounts needed | ||
| ro_bind_mounts: Vec::new(), // No additional ro bind mounts needed | ||
| systemd_units_dir: None, // No custom systemd units | ||
| bind_storage_ro: true, // Mount host container storage read-only | ||
| systemd_units_dir: Some(units_dir.path().to_string_lossy().to_string()), | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The (pre-existing, unrelated to this PR) implementation of |
||
| bind_storage_ro: true, // Mount host container storage read-only | ||
| mount_disk_files: vec![format!( | ||
| "{}:output:{}", | ||
| opts.target_disk, | ||
| opts.additional.format.as_str() | ||
| )], // Attach target disk | ||
| kernel_args: Default::default(), | ||
| kernel_args: vec!["systemd.unit=bcvk-to-disk.target".to_string()], | ||
| ignition_config: None, | ||
| debug_entrypoint: None, | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Boot target for bcvk to-disk ephemeral install VMs. | ||
| # | ||
| # The to-disk flow reuses the target image as the installer environment. | ||
| # Booting the full default.target could start user services (e.g. quadlets) | ||
| # that can interfere with the installation, e.g. by opening files under | ||
| # /var/lib/containers. This target starts only what the install needs: | ||
| # - basic.target (pulls in sysinit.target: udevd, journald, ...) | ||
| # - network-online.target and sshd.service (the host drives the install over SSH) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These types of comments are better right next to the |
||
| # - remote-fs.target (virtiofs host-storage mounts are wired here via SMBIOS creds) | ||
| [Unit] | ||
| Description=bcvk to-disk install target | ||
| Requires=basic.target network-online.target sshd.service | ||
| Wants=remote-fs.target | ||
| After=basic.target network-online.target sshd.service remote-fs.target | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test could also run with
--privilegedand runpoweroff, then we'd really know if quadlets started running unintentionally 😄