Skip to content

Commit d4acdce

Browse files
committed
install: Pull bound images by default
Unless overridden by a CLI option, in which case they will likely be pulled on firstboot. Signed-off-by: Colin Walters <[email protected]>
1 parent f791531 commit d4acdce

File tree

1 file changed

+73
-18
lines changed

1 file changed

+73
-18
lines changed

lib/src/install.rs

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use ostree_ext::container as ostree_container;
3535
use ostree_ext::oci_spec;
3636
use ostree_ext::ostree;
3737
use ostree_ext::prelude::Cast;
38+
use ostree_ext::sysroot::SysrootLock;
3839
use rustix::fs::{FileTypeExt, MetadataExt as _};
3940
use serde::{Deserialize, Serialize};
4041

@@ -160,6 +161,11 @@ pub(crate) struct InstallConfigOpts {
160161
#[clap(long)]
161162
#[serde(default)]
162163
pub(crate) generic_image: bool,
164+
165+
/// Do not pull any "logically bound" images at install time.
166+
#[clap(long, hide = true)]
167+
#[serde(default)]
168+
pub(crate) skip_bound_images: bool,
163169
}
164170

165171
#[derive(Debug, Clone, clap::Parser, Serialize, Deserialize, PartialEq, Eq)]
@@ -1219,23 +1225,21 @@ async fn prepare_install(
12191225
Ok(state)
12201226
}
12211227

1222-
async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Result<()> {
1223-
if matches!(state.selinux_state, SELinuxFinalState::ForceTargetDisabled) {
1224-
rootfs.kargs.push("selinux=0".to_string());
1225-
}
1226-
1227-
// We verify this upfront because it's currently required by bootupd
1228-
let boot_uuid = rootfs
1229-
.get_boot_uuid()?
1230-
.or(rootfs.rootfs_uuid.as_deref())
1231-
.ok_or_else(|| anyhow!("No uuid for boot/root"))?;
1232-
tracing::debug!("boot uuid={boot_uuid}");
1233-
1234-
// Initialize the ostree sysroot (repo, stateroot, etc.)
1235-
let sysroot = initialize_ostree_root(state, rootfs).await?;
1228+
/// Given a baseline root filesystem with an ostree sysroot initialized:
1229+
/// - install the container to that root
1230+
/// - install the bootloader
1231+
/// - Other post operations, such as pulling bound images
1232+
async fn install_with_sysroot(
1233+
state: &State,
1234+
rootfs: &RootSetup,
1235+
sysroot: &ostree::Sysroot,
1236+
boot_uuid: &str,
1237+
) -> Result<()> {
1238+
let sysroot = SysrootLock::new_from_sysroot(&sysroot).await?;
12361239
// And actually set up the container in that root, returning a deployment and
12371240
// the aleph state (see below).
12381241
let (deployment, aleph) = install_container(state, rootfs, &sysroot).await?;
1242+
let stateroot = deployment.osname();
12391243
// Write the aleph data that captures the system state at the time of provisioning for aid in future debugging.
12401244
rootfs
12411245
.rootfs_fd
@@ -1244,6 +1248,7 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
12441248
anyhow::Ok(())
12451249
})
12461250
.context("Writing aleph version")?;
1251+
12471252
if cfg!(target_arch = "s390x") {
12481253
// TODO: Integrate s390x support into install_via_bootupd
12491254
crate::bootloader::install_via_zipl(&rootfs.device_info, boot_uuid)?;
@@ -1254,12 +1259,62 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
12541259
&state.config_opts,
12551260
)?;
12561261
}
1262+
tracing::debug!("Installed bootloader");
12571263

1258-
// After this point, we need to drop all open references to the filesystem
1259-
drop(deployment);
1260-
drop(sysroot);
1264+
tracing::debug!("Perfoming post-deployment operations");
1265+
let deployment_root = crate::utils::deployment_fd(&sysroot, &deployment)?;
1266+
let bound_images = if state.config_opts.skip_bound_images {
1267+
Vec::new()
1268+
} else {
1269+
crate::boundimage::query_bound_images(&deployment_root)?
1270+
};
1271+
if !bound_images.is_empty() {
1272+
// TODO: We only do this dance to initialize `/var` at install time if
1273+
// there are bound images today; it minimizes side effects.
1274+
// However going forward we really do need to handle a separate /var partition...
1275+
// and to do that we may in the general case need to run the `var.mount`
1276+
// target from the new root.
1277+
let varpath = format!("ostree/deploy/{stateroot}/var");
1278+
let var = rootfs
1279+
.rootfs_fd
1280+
.open_dir(&varpath)
1281+
.with_context(|| format!("Opening {varpath}"))?;
1282+
Task::new("Mounting deployment /var", "mount")
1283+
.args(["--bind", ".", "/var"])
1284+
.cwd(&var)?
1285+
.run()?;
1286+
// podman needs this
1287+
Task::new("Initializing /var/tmp", "systemd-tmpfiles")
1288+
.args(["--create", "--boot", "--prefix=/var/tmp"])
1289+
.verbose()
1290+
.run()?;
1291+
crate::boundimage::pull_images(&deployment_root, bound_images)?;
1292+
}
12611293

1262-
tracing::debug!("Installed bootloader");
1294+
Ok(())
1295+
}
1296+
1297+
async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Result<()> {
1298+
if matches!(state.selinux_state, SELinuxFinalState::ForceTargetDisabled) {
1299+
rootfs.kargs.push("selinux=0".to_string());
1300+
}
1301+
// Drop exclusive ownership since we're done with mutation
1302+
let rootfs = &*rootfs;
1303+
1304+
// We verify this upfront because it's currently required by bootupd
1305+
let boot_uuid = rootfs
1306+
.get_boot_uuid()?
1307+
.or(rootfs.rootfs_uuid.as_deref())
1308+
.ok_or_else(|| anyhow!("No uuid for boot/root"))?;
1309+
tracing::debug!("boot uuid={boot_uuid}");
1310+
1311+
// Initialize the ostree sysroot (repo, stateroot, etc.)
1312+
{
1313+
let sysroot = initialize_ostree_root(state, rootfs).await?;
1314+
install_with_sysroot(state, rootfs, &sysroot, &boot_uuid).await?;
1315+
// We must drop the sysroot here in order to close any open file
1316+
// descriptors.
1317+
}
12631318

12641319
// Finalize mounted filesystems
12651320
if !rootfs.skip_finalize {

0 commit comments

Comments
 (0)