Skip to content

Commit 26bc174

Browse files
authored
Merge pull request #674 from cgwalters/karg-cleanup-2
kargs: More cleanups
2 parents 6ba4025 + 5452ae6 commit 26bc174

File tree

4 files changed

+56
-32
lines changed

4 files changed

+56
-32
lines changed

lib/src/cli.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,6 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
541541
}
542542
} else {
543543
let fetched = crate::deploy::pull(repo, imgref, opts.quiet).await?;
544-
let kargs = crate::kargs::get_kargs(repo, &booted_deployment, fetched.as_ref())?;
545544
let staged_digest = staged_image.as_ref().map(|s| s.image_digest.as_str());
546545
let fetched_digest = fetched.manifest_digest.as_str();
547546
tracing::debug!("staged: {staged_digest:?}");
@@ -563,10 +562,7 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
563562
println!("No update available.")
564563
} else {
565564
let osname = booted_deployment.osname();
566-
let mut opts = ostree::SysrootDeployTreeOpts::default();
567-
let kargs: Vec<&str> = kargs.iter().map(|s| s.as_str()).collect();
568-
opts.override_kernel_argv = Some(kargs.as_slice());
569-
crate::deploy::stage(sysroot, &osname, &fetched, &spec, Some(opts)).await?;
565+
crate::deploy::stage(sysroot, &osname, &fetched, &spec).await?;
570566
changed = true;
571567
if let Some(prev) = booted_image.as_ref() {
572568
if let Some(fetched_manifest) = fetched.get_manifest(repo)? {
@@ -638,7 +634,6 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
638634
let new_spec = RequiredHostSpec::from_spec(&new_spec)?;
639635

640636
let fetched = crate::deploy::pull(repo, &target, opts.quiet).await?;
641-
let kargs = crate::kargs::get_kargs(repo, &booted_deployment, fetched.as_ref())?;
642637

643638
if !opts.retain {
644639
// By default, we prune the previous ostree ref so it will go away after later upgrades
@@ -652,10 +647,7 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
652647
}
653648

654649
let stateroot = booted_deployment.osname();
655-
let mut opts = ostree::SysrootDeployTreeOpts::default();
656-
let kargs: Vec<&str> = kargs.iter().map(|s| s.as_str()).collect();
657-
opts.override_kernel_argv = Some(kargs.as_slice());
658-
crate::deploy::stage(sysroot, &stateroot, &fetched, &new_spec, Some(opts)).await?;
650+
crate::deploy::stage(sysroot, &stateroot, &fetched, &new_spec).await?;
659651

660652
Ok(())
661653
}
@@ -700,15 +692,11 @@ async fn edit(opts: EditOpts) -> Result<()> {
700692
}
701693

702694
let fetched = crate::deploy::pull(repo, new_spec.image, opts.quiet).await?;
703-
let kargs = crate::kargs::get_kargs(repo, &booted_deployment, fetched.as_ref())?;
704695

705696
// TODO gc old layers here
706697

707698
let stateroot = booted_deployment.osname();
708-
let mut opts = ostree::SysrootDeployTreeOpts::default();
709-
let kargs: Vec<&str> = kargs.iter().map(|s| s.as_str()).collect();
710-
opts.override_kernel_argv = Some(kargs.as_slice());
711-
crate::deploy::stage(sysroot, &stateroot, &fetched, &new_spec, Some(opts)).await?;
699+
crate::deploy::stage(sysroot, &stateroot, &fetched, &new_spec).await?;
712700

713701
Ok(())
714702
}

lib/src/deploy.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,26 @@ async fn deploy(
327327
stateroot: &str,
328328
image: &ImageState,
329329
origin: &glib::KeyFile,
330-
opts: Option<ostree::SysrootDeployTreeOpts<'_>>,
331330
) -> Result<Deployment> {
332331
let stateroot = Some(stateroot);
333-
let opts = opts.unwrap_or_default();
332+
let mut opts = ostree::SysrootDeployTreeOpts::default();
333+
// Compute the kernel argument overrides. In practice today this API is always expecting
334+
// a merge deployment. The kargs code also always looks at the booted root (which
335+
// is a distinct minor issue, but not super important as right now the install path
336+
// doesn't use this API).
337+
let override_kargs = if let Some(deployment) = merge_deployment {
338+
Some(crate::kargs::get_kargs(sysroot, &deployment, image)?)
339+
} else {
340+
None
341+
};
342+
// Because the C API expects a Vec<&str>, we need to generate a new Vec<>
343+
// that borrows.
344+
let override_kargs = override_kargs
345+
.as_deref()
346+
.map(|v| v.iter().map(|s| s.as_str()).collect::<Vec<_>>());
347+
if let Some(kargs) = override_kargs.as_deref() {
348+
opts.override_kernel_argv = Some(&kargs);
349+
}
334350
// Copy to move into thread
335351
let cancellable = gio::Cancellable::NONE;
336352
return sysroot
@@ -364,7 +380,6 @@ pub(crate) async fn stage(
364380
stateroot: &str,
365381
image: &ImageState,
366382
spec: &RequiredHostSpec<'_>,
367-
opts: Option<ostree::SysrootDeployTreeOpts<'_>>,
368383
) -> Result<()> {
369384
let merge_deployment = sysroot.merge_deployment(Some(stateroot));
370385
let origin = origin_from_imageref(spec.image)?;
@@ -374,7 +389,6 @@ pub(crate) async fn stage(
374389
stateroot,
375390
image,
376391
&origin,
377-
opts,
378392
)
379393
.await?;
380394
crate::deploy::cleanup(sysroot).await?;

lib/src/kargs.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use anyhow::{Context, Result};
22
use camino::Utf8Path;
3-
use cap_std_ext::cap_std;
43
use cap_std_ext::cap_std::fs::Dir;
54
use cap_std_ext::dirext::CapStdExtDirExt;
65
use ostree::gio;
@@ -9,6 +8,7 @@ use ostree_ext::ostree::Deployment;
98
use ostree_ext::prelude::Cast;
109
use ostree_ext::prelude::FileEnumeratorExt;
1110
use ostree_ext::prelude::FileExt;
11+
use ostree_ext::sysroot::SysrootLock;
1212
use serde::Deserialize;
1313

1414
use crate::deploy::ImageState;
@@ -101,25 +101,26 @@ fn get_kargs_from_ostree(
101101
/// karg, but applies the diff between the bootc karg files in /usr/lib/bootc/kargs.d
102102
/// between the booted deployment and the new one.
103103
pub(crate) fn get_kargs(
104-
repo: &ostree::Repo,
105-
booted_deployment: &Deployment,
104+
sysroot: &SysrootLock,
105+
merge_deployment: &Deployment,
106106
fetched: &ImageState,
107107
) -> Result<Vec<String>> {
108108
let cancellable = gio::Cancellable::NONE;
109-
let mut kargs: Vec<String> = vec![];
109+
let repo = &sysroot.repo();
110+
let mut kargs = vec![];
110111
let sys_arch = std::env::consts::ARCH;
111112

112-
// Get the running kargs of the booted system
113-
if let Some(bootconfig) = ostree::Deployment::bootconfig(booted_deployment) {
113+
// Get the kargs used for the merge in the bootloader config
114+
if let Some(bootconfig) = ostree::Deployment::bootconfig(merge_deployment) {
114115
if let Some(options) = ostree::BootconfigParser::get(&bootconfig, "options") {
115116
let options = options.split_whitespace().map(|s| s.to_owned());
116117
kargs.extend(options);
117118
}
118119
};
119120

120-
// Get the kargs in kargs.d of the booted system
121-
let root = &cap_std::fs::Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
122-
let existing_kargs: Vec<String> = get_kargs_in_root(root, sys_arch)?;
121+
// Get the kargs in kargs.d of the merge
122+
let merge_root = &crate::utils::deployment_fd(sysroot, merge_deployment)?;
123+
let existing_kargs = get_kargs_in_root(merge_root, sys_arch)?;
123124

124125
// Get the kargs in kargs.d of the pending image
125126
let (fetched_tree, _) = repo.read_commit(fetched.ostree_commit.as_str(), cancellable)?;
@@ -138,16 +139,16 @@ pub(crate) fn get_kargs(
138139
let remote_kargs = get_kargs_from_ostree(repo, &fetched_tree, sys_arch)?;
139140

140141
// get the diff between the existing and remote kargs
141-
let mut added_kargs: Vec<String> = remote_kargs
142+
let mut added_kargs = remote_kargs
142143
.clone()
143144
.into_iter()
144145
.filter(|item| !existing_kargs.contains(item))
145-
.collect();
146-
let removed_kargs: Vec<String> = existing_kargs
146+
.collect::<Vec<_>>();
147+
let removed_kargs = existing_kargs
147148
.clone()
148149
.into_iter()
149150
.filter(|item| !remote_kargs.contains(item))
150-
.collect();
151+
.collect::<Vec<_>>();
151152

152153
tracing::debug!(
153154
"kargs: added={:?} removed={:?}",
@@ -179,6 +180,7 @@ fn parse_kargs_toml(contents: &str, sys_arch: &str) -> Result<Vec<String>> {
179180

180181
#[cfg(test)]
181182
mod tests {
183+
use cap_std_ext::cap_std;
182184
use fn_error_context::context;
183185
use rustix::fd::{AsFd, AsRawFd};
184186

lib/src/utils.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use std::future::Future;
22
use std::io::Write;
3+
use std::os::fd::BorrowedFd;
34
use std::process::Command;
45
use std::time::Duration;
56

67
use anyhow::{Context, Result};
8+
use cap_std_ext::cap_std::fs::Dir;
79
use ostree::glib;
810
use ostree_ext::container::SignatureSource;
911
use ostree_ext::ostree;
@@ -21,6 +23,24 @@ pub(crate) fn origin_has_rpmostree_stuff(kf: &glib::KeyFile) -> bool {
2123
false
2224
}
2325

26+
// Access the file descriptor for a sysroot
27+
#[allow(unsafe_code)]
28+
pub(crate) fn sysroot_fd(sysroot: &ostree::Sysroot) -> BorrowedFd {
29+
unsafe { BorrowedFd::borrow_raw(sysroot.fd()) }
30+
}
31+
32+
// Return a cap-std `Dir` type for a deployment.
33+
// TODO: in the future this should perhaps actually mount via composefs
34+
#[allow(unsafe_code)]
35+
pub(crate) fn deployment_fd(
36+
sysroot: &ostree::Sysroot,
37+
deployment: &ostree::Deployment,
38+
) -> Result<Dir> {
39+
let sysroot_dir = &Dir::reopen_dir(&sysroot_fd(sysroot))?;
40+
let dirpath = sysroot.deployment_dirpath(deployment);
41+
sysroot_dir.open_dir(&dirpath).map_err(Into::into)
42+
}
43+
2444
/// Given an mount option string list like foo,bar=baz,something=else,ro parse it and find
2545
/// the first entry like $optname=
2646
/// This will not match a bare `optname` without an equals.

0 commit comments

Comments
 (0)