Add missing file

This commit is contained in:
Luke D. Jones
2022-10-11 22:25:49 +13:00
parent e0ed52092a
commit ba1d3f045d

90
daemon/src/systemd.rs Normal file
View File

@@ -0,0 +1,90 @@
use std::process::Command;
use crate::error::RogError;
/// An action for `systemctl`
#[derive(Debug, Copy, Clone)]
pub enum SystemdUnitAction {
Stop,
Start,
Restart,
}
impl From<SystemdUnitAction> for &str {
fn from(s: SystemdUnitAction) -> Self {
match s {
SystemdUnitAction::Stop => "stop",
SystemdUnitAction::Start => "start",
SystemdUnitAction::Restart => "restart",
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum SystemdUnitState {
Active,
Inactive,
}
impl From<SystemdUnitState> for &str {
fn from(s: SystemdUnitState) -> Self {
match s {
SystemdUnitState::Active => "active",
SystemdUnitState::Inactive => "inactive",
}
}
}
/// Change the state of a systemd unit. Blocks while running command.
pub fn do_systemd_unit_action(action: SystemdUnitAction, unit: &str) -> Result<(), RogError> {
let mut cmd = Command::new("systemctl");
cmd.arg(<&str>::from(action));
cmd.arg(unit);
let status = cmd
.status()
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
if !status.success() {
let msg = format!("systemctl {action:?} {unit} failed: {status:?}",);
return Err(RogError::SystemdUnitAction(msg));
}
Ok(())
}
/// Get systemd unit state. Blocks while command is run.
pub fn is_systemd_unit_state(state: SystemdUnitState, unit: &str) -> Result<bool, RogError> {
let mut cmd = Command::new("systemctl");
cmd.arg("is-active");
cmd.arg(unit);
let output = cmd
.output()
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
if output.stdout.starts_with(<&str>::from(state).as_bytes()) {
return Ok(true);
}
Ok(false)
}
/// Wait for a systemd unit to change to `state`. Checks state every 250ms for 3 seconds. Blocks while running wait.
pub fn wait_systemd_unit_state(state: SystemdUnitState, unit: &str) -> Result<(), RogError> {
let mut cmd = Command::new("systemctl");
cmd.arg("is-active");
cmd.arg(unit);
let mut count = 0;
while count <= (4 * 3) {
// 3 seconds max
let output = cmd
.output()
.map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
if output.stdout.starts_with(<&str>::from(state).as_bytes()) {
return Ok(());
}
// fine to block here, nobody doing shit now
std::thread::sleep(std::time::Duration::from_millis(250));
count += 1;
}
Err(RogError::SystemdUnitWaitTimeout(<&str>::from(state).into()))
}