81 lines
2.3 KiB
Rust
81 lines
2.3 KiB
Rust
use std::{fs, process::Command};
|
|
|
|
use crate::config::Config;
|
|
|
|
pub fn ensure_swap(cfg: &Config) -> anyhow::Result<()> {
|
|
if !cfg.swap.enabled {
|
|
return Ok(());
|
|
}
|
|
|
|
let path = &cfg.swap.path;
|
|
let expected_size = cfg.swap.size_mb * 1024 * 1024;
|
|
if std::path::Path::new(path).exists() {
|
|
let actual_size = fs::metadata(path)?.len();
|
|
if actual_size != expected_size {
|
|
anyhow::bail!(
|
|
"existing swapfile has wrong size: {} bytes, expected {} bytes; manual intervention required",
|
|
actual_size,
|
|
expected_size
|
|
);
|
|
}
|
|
} else {
|
|
run(
|
|
"fallocate",
|
|
&["-l", &format!("{}M", cfg.swap.size_mb), path],
|
|
)?;
|
|
run("chmod", &["600", path])?;
|
|
run("mkswap", &[path])?;
|
|
}
|
|
|
|
let swapon = Command::new("swapon").args(["--show"]).output()?;
|
|
let active = String::from_utf8_lossy(&swapon.stdout);
|
|
if !active.contains(path) {
|
|
run("swapon", &["-p", &cfg.swap.priority.to_string(), path])?;
|
|
}
|
|
|
|
ensure_fstab(path, cfg.swap.priority)?;
|
|
run(
|
|
"sysctl",
|
|
&["-w", &format!("vm.swappiness={}", cfg.swap.swappiness)],
|
|
)?;
|
|
ensure_swappiness_persist(cfg.swap.swappiness)?;
|
|
Ok(())
|
|
}
|
|
|
|
fn ensure_fstab(path: &str, priority: i32) -> anyhow::Result<()> {
|
|
let file = "/etc/fstab";
|
|
let content = fs::read_to_string(file).unwrap_or_default();
|
|
if content
|
|
.lines()
|
|
.any(|l| l.contains(path) && l.contains("swap"))
|
|
{
|
|
return Ok(());
|
|
}
|
|
let line = format!("{path} none swap sw,pri={priority} 0 0\n");
|
|
fs::write(file, format!("{}{}", content, line))?;
|
|
Ok(())
|
|
}
|
|
|
|
fn run(program: &str, args: &[&str]) -> anyhow::Result<()> {
|
|
let out = Command::new(program).args(args).output()?;
|
|
if !out.status.success() {
|
|
anyhow::bail!(
|
|
"{} {:?} failed: {}",
|
|
program,
|
|
args,
|
|
String::from_utf8_lossy(&out.stderr)
|
|
);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn ensure_swappiness_persist(swappiness: u8) -> anyhow::Result<()> {
|
|
let conf_path = "/etc/sysctl.d/99-awg2-harness.conf";
|
|
let expected = format!("vm.swappiness = {}\n", swappiness);
|
|
let current = fs::read_to_string(conf_path).unwrap_or_default();
|
|
if current != expected {
|
|
fs::write(conf_path, expected)?;
|
|
}
|
|
Ok(())
|
|
}
|