Implement resizing of zpool
Some checks failed
/ dev-shell (push) Successful in 2m7s
/ rust-packages (push) Successful in 2m22s
/ terraform-providers (push) Successful in 53s
/ check (push) Failing after 3m31s
/ systems (push) Successful in 26m15s

This commit is contained in:
Kaare Hoff Skovgaard 2025-08-04 02:20:26 +02:00
parent f410517ffa
commit f0725c503f
Signed by: khs
GPG key ID: C7D890804F01E9F0
10 changed files with 234 additions and 17 deletions

View file

@ -308,21 +308,67 @@ impl Command {
cmd.status()
.with_context(|| format!("Could not spawn command: {}", command_to_string(self)))
}
pub fn spawn_into_parts(&mut self) -> anyhow::Result<(String, String, ExitStatus)> {
let mut cmd = self.as_command();
let mut child = cmd
.stderr(self.stderr.as_std_stdio())
.stdin(self.stdin.as_std_stdio())
.stdout(Stdio::piped())
.spawn()
.with_context(|| format!("Could not spawn command: {}", command_to_string(self)))?;
let mut stdin = Stdin::Null;
std::mem::swap(&mut self.stdin, &mut stdin);
let join_handle = if let Some(data) = stdin.into_data() {
let mut stdin_pipe = child.stdin.take().expect("Child has no stdin");
Some(std::thread::spawn(move || {
stdin_pipe
.write_all(data.as_slice())
.expect("Could not write to child");
}))
} else {
None
};
let output: Result<(Vec<u8>, Vec<u8>, ExitStatus), anyhow::Error> =
wait_with_output_into_parts(child, || command_to_string(self));
if let Some(join_handle) = join_handle {
join_handle
.join()
.map_err(|e| anyhow::format_err!("Thread sending stdin panicked: {e:?}"))?;
}
let (stdout, stderr, status) = output?;
let stdout =
String::from_utf8(stdout).context("Could not read stdout of command as UTF-8")?;
let stderr =
String::from_utf8(stderr).context("Could not read stderr of command as UTF-8")?;
Ok((stdout, stderr, status))
}
}
fn wait_with_output(child: Child, cmd_str: impl Fn() -> String) -> anyhow::Result<Vec<u8>> {
let output = child
.wait_with_output()
.with_context(|| format!("Could not wait for output of commnad: {}", cmd_str()))?;
if !output.status.success() {
fn wait_with_output(child: Child, cmd_str: impl Fn() -> String + Clone) -> anyhow::Result<Vec<u8>> {
let (stdout, stderr, status) = wait_with_output_into_parts(child, cmd_str.clone())?;
if !status.success() {
return Err(anyhow::format_err!(
"Command {}, exited unexpectedly: {:?}. With stderr: {}",
cmd_str(),
output.status,
String::from_utf8_lossy(&output.stderr),
status,
String::from_utf8_lossy(&stderr),
));
}
Ok(output.stdout)
Ok(stdout)
}
fn wait_with_output_into_parts(
child: Child,
cmd_str: impl Fn() -> String,
) -> anyhow::Result<(Vec<u8>, Vec<u8>, ExitStatus)> {
let output = child
.wait_with_output()
.with_context(|| format!("Could not wait for output of commnad: {}", cmd_str()))?;
let status = output.status;
let stdout = output.stdout;
let stderr = output.stderr;
Ok((stdout, stderr, status))
}
#[cfg(test)]