proxmox-backup/proxmox-systemd/src/unit.rs

128 lines
3.2 KiB
Rust

use std::process::Command;
use anyhow::{bail, format_err, Error};
fn run_command(mut command: Command) -> Result<(), Error> {
let output = command
.output()
.map_err(|err| format_err!("failed to execute {:?} - {}", command, err))?;
proxmox::try_block!({
if !output.status.success() {
match output.status.code() {
Some(code) => {
if code != 0 {
let msg = String::from_utf8(output.stderr)
.map(|m| {
if m.is_empty() {
String::from("no error message")
} else {
m
}
})
.unwrap_or_else(|_| String::from("non utf8 error message (suppressed)"));
bail!("status code: {} - {}", code, msg);
}
}
None => bail!("terminated by signal"),
}
}
Ok(())
}).map_err(|err| format_err!("command {:?} failed - {}", command, err))?;
Ok(())
}
pub fn reload_daemon() -> Result<(), Error> {
let mut command = std::process::Command::new("systemctl");
command.arg("daemon-reload");
run_command(command)?;
Ok(())
}
pub fn disable_unit(unit: &str) -> Result<(), Error> {
let mut command = std::process::Command::new("systemctl");
command.arg("disable");
command.arg(unit);
run_command(command)?;
Ok(())
}
pub fn enable_unit(unit: &str) -> Result<(), Error> {
let mut command = std::process::Command::new("systemctl");
command.arg("enable");
command.arg(unit);
run_command(command)?;
Ok(())
}
pub fn start_unit(unit: &str) -> Result<(), Error> {
let mut command = std::process::Command::new("systemctl");
command.arg("start");
command.arg(unit);
run_command(command)?;
Ok(())
}
pub fn stop_unit(unit: &str) -> Result<(), Error> {
let mut command = std::process::Command::new("systemctl");
command.arg("stop");
command.arg(unit);
run_command(command)?;
Ok(())
}
pub fn reload_unit(unit: &str) -> Result<(), Error> {
let mut command = std::process::Command::new("systemctl");
command.arg("try-reload-or-restart");
command.arg(unit);
run_command(command)?;
Ok(())
}
#[test]
fn test_escape_unit() -> Result<(), Error> {
fn test_escape(i: &str, expected: &str, is_path: bool) {
use proxmox::tools::systemd::{escape_unit, unescape_unit};
let escaped = escape_unit(i, is_path);
assert_eq!(escaped, expected);
let unescaped = unescape_unit(&escaped).unwrap();
if is_path {
let mut p = i.trim_matches('/');
if p.is_empty() {
p = "/";
}
assert_eq!(p, unescaped);
} else {
assert_eq!(i, unescaped);
}
}
test_escape(".test", "\\x2etest", false);
test_escape("t.est", "t.est", false);
test_escape("_test_", "_test_", false);
test_escape("/", "-", false);
test_escape("//", "--", false);
test_escape("/", "-", true);
test_escape("//", "-", true);
Ok(())
}