Skip to content

Commit 6ba7938

Browse files
authored
Merge pull request #488 from cgwalters/install-more-info
install: Two informational patches
2 parents ea4af04 + 2914c31 commit 6ba7938

File tree

2 files changed

+83
-33
lines changed

2 files changed

+83
-33
lines changed

lib/src/install/baseline.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,17 @@ impl Display for Filesystem {
5050
}
5151
}
5252

53-
#[derive(clap::ValueEnum, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
53+
#[derive(clap::ValueEnum, Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
5454
#[serde(rename_all = "kebab-case")]
5555
pub(crate) enum BlockSetup {
56+
#[default]
5657
Direct,
5758
Tpm2Luks,
5859
}
5960

60-
impl Default for BlockSetup {
61-
fn default() -> Self {
62-
Self::Direct
61+
impl Display for BlockSetup {
62+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63+
self.to_possible_value().unwrap().get_name().fmt(f)
6364
}
6465
}
6566

@@ -113,11 +114,14 @@ fn sgdisk_partition(
113114
fn mkfs<'a>(
114115
dev: &str,
115116
fs: Filesystem,
116-
label: Option<&'_ str>,
117+
label: &str,
117118
opts: impl IntoIterator<Item = &'a str>,
118119
) -> Result<uuid::Uuid> {
119120
let u = uuid::Uuid::new_v4();
120-
let mut t = Task::new("Creating filesystem", format!("mkfs.{fs}"));
121+
let mut t = Task::new(
122+
&format!("Creating {label} filesystem ({fs})"),
123+
format!("mkfs.{fs}"),
124+
);
121125
match fs {
122126
Filesystem::Xfs => {
123127
t.cmd.arg("-m");
@@ -129,14 +133,13 @@ fn mkfs<'a>(
129133
}
130134
};
131135
// Today all the above mkfs commands take -L
132-
if let Some(label) = label {
133-
t.cmd.args(["-L", label]);
134-
}
136+
t.cmd.args(["-L", label]);
135137
t.cmd.args(opts);
136138
t.cmd.arg(dev);
137139
// All the mkfs commands are unnecessarily noisy by default
138140
t.cmd.stdout(Stdio::null());
139-
t.run()?;
141+
// But this one is notable so let's print the whole thing with verbose()
142+
t.verbose().run()?;
140143
Ok(u)
141144
}
142145

@@ -196,6 +199,20 @@ pub(crate) fn install_create_rootfs(
196199
.context("Absolute device path in /dev/ required")?;
197200
let device = devdir.join(reldevice);
198201

202+
// Use the install configuration to find the block setup, if we have one
203+
let block_setup = if let Some(config) = state.install_config.as_ref() {
204+
config.get_block_setup(opts.block_setup.as_ref().copied())?
205+
} else if opts.filesystem.is_some() {
206+
// Otherwise, if a filesystem is specified then we default to whatever was
207+
// specified via --block-setup, or the default
208+
opts.block_setup.unwrap_or_default()
209+
} else {
210+
// If there was no default filesystem, then there's no default block setup,
211+
// and we need to error out.
212+
anyhow::bail!("No install configuration found, and no filesystem specified")
213+
};
214+
println!("Using block setup: {block_setup}");
215+
199216
let root_size = opts
200217
.root_size
201218
.as_deref()
@@ -305,18 +322,7 @@ pub(crate) fn install_create_rootfs(
305322
};
306323

307324
let base_rootdev = findpart(ROOTPN)?;
308-
// Use the install configuration to find the block setup, if we have one
309-
let block_setup = if let Some(config) = state.install_config.as_ref() {
310-
config.get_block_setup(opts.block_setup.as_ref().copied())?
311-
} else if opts.filesystem.is_some() {
312-
// Otherwise, if a filesystem is specified then we default to whatever was
313-
// specified via --block-setup, or the default
314-
opts.block_setup.unwrap_or_default()
315-
} else {
316-
// If there was no default filesystem, then there's no default block setup,
317-
// and we need to error out.
318-
anyhow::bail!("No install configuration found, and no filesystem specified")
319-
};
325+
320326
let (rootdev, root_blockdev_kargs) = match block_setup {
321327
BlockSetup::Direct => (base_rootdev, None),
322328
BlockSetup::Tpm2Luks => {
@@ -335,10 +341,12 @@ pub(crate) fn install_create_rootfs(
335341
.args([base_rootdev.as_str()])
336342
.run()?;
337343
// The --wipe-slot=all removes our temporary passphrase, and binds to the local TPM device.
344+
// We also use .verbose() here as the details are important/notable.
338345
Task::new("Enrolling root device with TPM", "systemd-cryptenroll")
339346
.args(["--wipe-slot=all", "--tpm2-device=auto", "--unlock-key-file"])
340347
.args([tmp_keyfile])
341348
.args([base_rootdev.as_str()])
349+
.verbose()
342350
.run_with_stdin_buf(dummy_passphrase_input)?;
343351
Task::new("Opening root LUKS device", "cryptsetup")
344352
.args(["luksOpen", base_rootdev.as_str(), luks_name])
@@ -357,10 +365,10 @@ pub(crate) fn install_create_rootfs(
357365

358366
// Initialize the /boot filesystem
359367
let bootdev = &findpart(BOOTPN)?;
360-
let boot_uuid = mkfs(bootdev, bootfs_type, Some("boot"), []).context("Initializing /boot")?;
368+
let boot_uuid = mkfs(bootdev, bootfs_type, "boot", []).context("Initializing /boot")?;
361369

362370
// Initialize rootfs
363-
let root_uuid = mkfs(&rootdev, root_filesystem, Some("root"), [])?;
371+
let root_uuid = mkfs(&rootdev, root_filesystem, "root", [])?;
364372
let rootarg = format!("root=UUID={root_uuid}");
365373
let bootsrc = format!("UUID={boot_uuid}");
366374
let bootarg = format!("boot={bootsrc}");

lib/src/task.rs

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,21 @@ use cap_std::fs::Dir;
99
use cap_std_ext::cap_std;
1010
use cap_std_ext::prelude::CapStdExtCommandExt;
1111

12+
/// How much information we output
13+
#[derive(Debug, PartialEq, Eq, Default)]
14+
enum CmdVerbosity {
15+
/// Nothing is output
16+
Quiet,
17+
/// Only the task description is output
18+
#[default]
19+
Description,
20+
/// The task description and the full command line are output
21+
Verbose,
22+
}
23+
1224
pub(crate) struct Task {
1325
description: String,
14-
quiet: bool,
26+
verbosity: CmdVerbosity,
1527
quiet_output: bool,
1628
pub(crate) cmd: Command,
1729
}
@@ -40,14 +52,21 @@ impl Task {
4052
cmd.stdin(Stdio::null());
4153
Self {
4254
description,
43-
quiet: false,
55+
verbosity: Default::default(),
4456
quiet_output: false,
4557
cmd,
4658
}
4759
}
4860

61+
/// Don't output description by default
4962
pub(crate) fn quiet(mut self) -> Self {
50-
self.quiet = true;
63+
self.verbosity = CmdVerbosity::Quiet;
64+
self
65+
}
66+
67+
/// Output description and cmdline
68+
pub(crate) fn verbose(mut self) -> Self {
69+
self.verbosity = CmdVerbosity::Verbose;
5170
self
5271
}
5372

@@ -72,13 +91,38 @@ impl Task {
7291
self.run_with_stdin_buf(None)
7392
}
7493

94+
fn pre_run_output(&self) {
95+
match self.verbosity {
96+
CmdVerbosity::Quiet => {}
97+
CmdVerbosity::Description => {
98+
println!("{}", self.description);
99+
}
100+
CmdVerbosity::Verbose => {
101+
// Output the description first
102+
println!("{}", self.description);
103+
104+
// Lock stdout so we buffer
105+
let mut stdout = std::io::stdout().lock();
106+
let cmd_args = std::iter::once(self.cmd.get_program())
107+
.chain(self.cmd.get_args())
108+
.map(|arg| arg.to_string_lossy());
109+
// We unwrap() here to match the default for println!() even though
110+
// arguably that's wrong
111+
stdout.write_all(b">").unwrap();
112+
for s in cmd_args {
113+
stdout.write_all(b" ").unwrap();
114+
stdout.write_all(s.as_bytes()).unwrap();
115+
}
116+
stdout.write_all(b"\n").unwrap();
117+
}
118+
}
119+
}
120+
75121
/// Run the command with optional stdin buffer, returning an error if the command does not exit successfully.
76122
pub(crate) fn run_with_stdin_buf(self, stdin: Option<&[u8]>) -> Result<()> {
123+
self.pre_run_output();
77124
let description = self.description;
78125
let mut cmd = self.cmd;
79-
if !self.quiet {
80-
println!("{description}");
81-
}
82126
let mut output = None;
83127
if self.quiet_output {
84128
let tmpf = tempfile::tempfile()?;
@@ -117,11 +161,9 @@ impl Task {
117161

118162
/// Like [`run()`], but return stdout.
119163
pub(crate) fn read(self) -> Result<String> {
164+
self.pre_run_output();
120165
let description = self.description;
121166
let mut cmd = self.cmd;
122-
if !self.quiet {
123-
println!("{description}");
124-
}
125167
tracing::debug!("exec: {cmd:?}");
126168
cmd.stdout(Stdio::piped());
127169
let child = cmd

0 commit comments

Comments
 (0)