Line data Source code
1 : use std::path::Path;
2 :
3 : use anyhow::{anyhow, Context};
4 : use tracing::warn;
5 :
6 : pub const RESIZE_SWAP_BIN: &str = "/neonvm/bin/resize-swap";
7 :
8 0 : pub fn resize_swap(size_bytes: u64) -> anyhow::Result<()> {
9 0 : // run `/neonvm/bin/resize-swap --once {size_bytes}`
10 0 : //
11 0 : // Passing '--once' causes resize-swap to delete itself after successful completion, which
12 0 : // means that if compute_ctl restarts later, we won't end up calling 'swapoff' while
13 0 : // postgres is running.
14 0 : //
15 0 : // NOTE: resize-swap is not very clever. If present, --once MUST be the first arg.
16 0 : let child_result = std::process::Command::new("/usr/bin/sudo")
17 0 : .arg(RESIZE_SWAP_BIN)
18 0 : .arg("--once")
19 0 : .arg(size_bytes.to_string())
20 0 : .spawn();
21 0 :
22 0 : child_result
23 0 : .context("spawn() failed")
24 0 : .and_then(|mut child| child.wait().context("wait() failed"))
25 0 : .and_then(|status| match status.success() {
26 0 : true => Ok(()),
27 : false => {
28 : // The command failed. Maybe it was because the resize-swap file doesn't exist?
29 : // The --once flag causes it to delete itself on success so we don't disable swap
30 : // while postgres is running; maybe this is fine.
31 0 : match Path::new(RESIZE_SWAP_BIN).try_exists() {
32 0 : Err(_) | Ok(true) => Err(anyhow!("process exited with {status}")),
33 : // The path doesn't exist; we're actually ok
34 : Ok(false) => {
35 0 : warn!("ignoring \"not found\" error from resize-swap to avoid swapoff while compute is running");
36 0 : Ok(())
37 : },
38 : }
39 : }
40 0 : })
41 0 : // wrap any prior error with the overall context that we couldn't run the command
42 0 : .with_context(|| {
43 0 : format!("could not run `/usr/bin/sudo {RESIZE_SWAP_BIN} --once {size_bytes}`")
44 0 : })
45 0 : }
|