Skip to content

Commit e3f216d

Browse files
committed
generator: Conditinally enable bootc-status units
Right now this service fails in `bcvk run-ephemeral`, but also likely fails in any non-bootc system that has `subscription-manager` installed. A problem is that dependencies of units are started even if the dependee has a condition that disables it. This basically the target and path depend on `/run/ostree-booted` being present (which yes, won't work for composefs...) Tests: Covered by extant `012-test-unit-status.nu` Signed-off-by: Colin Walters <[email protected]>
1 parent 011c737 commit e3f216d

File tree

4 files changed

+45
-14
lines changed

4 files changed

+45
-14
lines changed

Makefile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ install:
3232
fi; \
3333
done
3434
install -D -m 0644 -t $(DESTDIR)/$(prefix)/lib/systemd/system systemd/*.service systemd/*.timer systemd/*.path systemd/*.target
35-
install -d -m 0755 $(DESTDIR)/$(prefix)/lib/systemd/system/multi-user.target.wants
36-
ln -s ../bootc-status-updated.path $(DESTDIR)/$(prefix)/lib/systemd/system/multi-user.target.wants/bootc-status-updated.path
37-
ln -s ../bootc-status-updated-onboot.target $(DESTDIR)/$(prefix)/lib/systemd/system/multi-user.target.wants/bootc-status-updated-onboot.target
3835
install -D -m 0644 -t $(DESTDIR)/$(prefix)/share/doc/bootc/baseimage/base/usr/lib/ostree/ baseimage/base/usr/lib/ostree/prepare-root.conf
3936
install -d -m 755 $(DESTDIR)/$(prefix)/share/doc/bootc/baseimage/base/sysroot
4037
cp -PfT baseimage/base/ostree $(DESTDIR)/$(prefix)/share/doc/bootc/baseimage/base/ostree

crates/lib/src/generator.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
use std::io::BufRead;
22

33
use anyhow::{Context, Result};
4+
use camino::Utf8PathBuf;
45
use cap_std::fs::Dir;
56
use cap_std_ext::{cap_std, dirext::CapStdExtDirExt};
67
use fn_error_context::context;
7-
use ostree_ext::container_utils::is_ostree_booted_in;
8+
use ostree_ext::container_utils::{is_ostree_booted_in, OSTREE_BOOTED};
89
use rustix::{fd::AsFd, fs::StatVfsMountFlags};
910

11+
const STATUS_ONBOOT_UNIT: &str = "bootc-status-updated-onboot.target";
12+
const STATUS_PATH_UNIT: &str = "bootc-status-updated.path";
13+
const MULTI_USER_TARGET: &str = "multi-user.target";
1014
const EDIT_UNIT: &str = "bootc-fstab-edit.service";
1115
const FSTAB_ANACONDA_STAMP: &str = "Created by anaconda";
1216
pub(crate) const BOOTC_EDITED_STAMP: &str = "Updated by bootc-fstab-edit.service";
@@ -47,9 +51,32 @@ pub(crate) fn fstab_generator_impl(root: &Dir, unit_dir: &Dir) -> Result<bool> {
4751
Ok(false)
4852
}
4953

54+
/// Enable our units
55+
pub(crate) fn unit_enablement_impl(unit_dir: &Dir) -> Result<()> {
56+
let wants = Utf8PathBuf::from(format!("{MULTI_USER_TARGET}.wants"));
57+
unit_dir.create_dir_all(&wants)?;
58+
let target = wants.join(STATUS_ONBOOT_UNIT);
59+
unit_dir.symlink_contents(
60+
format!("/usr/lib/systemd/system/{STATUS_ONBOOT_UNIT}"),
61+
&target,
62+
)?;
63+
unit_dir.symlink_contents(
64+
format!("/usr/lib/systemd/system/{STATUS_PATH_UNIT}"),
65+
&target,
66+
)?;
67+
Ok(())
68+
}
69+
5070
/// Main entrypoint for the generator
5171
pub(crate) fn generator(root: &Dir, unit_dir: &Dir) -> Result<()> {
52-
// Right now we only do something if the root is a read-only overlayfs (a composefs really)
72+
// Only run on ostree systems
73+
if !root.try_exists(OSTREE_BOOTED)? {
74+
return Ok(());
75+
}
76+
77+
unit_enablement_impl(unit_dir)?;
78+
79+
// Also only run if the root is a read-only overlayfs (a composefs really)
5380
let st = rustix::fs::fstatfs(root.as_fd())?;
5481
if st.f_type != libc::OVERLAYFS_SUPER_MAGIC {
5582
tracing::trace!("Root is not overlayfs");
@@ -62,6 +89,7 @@ pub(crate) fn generator(root: &Dir, unit_dir: &Dir) -> Result<()> {
6289
}
6390
let updated = fstab_generator_impl(root, unit_dir)?;
6491
tracing::trace!("Generated fstab: {updated}");
92+
6593
Ok(())
6694
}
6795

@@ -109,6 +137,19 @@ mod tests {
109137
Ok(())
110138
}
111139

140+
#[test]
141+
fn test_units() -> Result<()> {
142+
let tempdir = fixture()?;
143+
let unit_dir = &tempdir.open_dir("run/systemd/system")?;
144+
unit_enablement_impl(&unit_dir).unwrap();
145+
let r =
146+
unit_dir.read_link_contents(format!("multi-user.target.wants/{STATUS_ONBOOT_UNIT}"))?;
147+
let r: Utf8PathBuf = r.try_into().unwrap();
148+
assert_eq!(r, format!("/usr/lib/systemd/system/{STATUS_ONBOOT_UNIT}"));
149+
assert_eq!(unit_dir.entries()?.count(), 1);
150+
Ok(())
151+
}
152+
112153
#[cfg(test)]
113154
mod test {
114155
use super::*;
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
[Unit]
2-
Description=Target for bootc status changes on boot
2+
Description=Bootc status trigger state sync
33
Documentation=man:bootc-status-updated.target(8)
4-
ConditionPathExists=/run/ostree-booted
5-
6-
[Install]
7-
WantedBy=multi-user.target
4+
After=sysinit.target

systemd/bootc-status-updated.path

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
[Unit]
22
Description=Monitor bootc for status changes
33
Documentation=man:bootc-status-updated.path(8)
4-
ConditionPathExists=/run/ostree-booted
54

65
[Path]
76
PathChanged=/ostree/bootc
87
Unit=bootc-status-updated.target
9-
10-
[Install]
11-
WantedBy=multi-user.target

0 commit comments

Comments
 (0)