From ba1d3f045d0fca79f125c165fd3cf34da249b506 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Tue, 11 Oct 2022 22:25:49 +1300 Subject: [PATCH] Add missing file --- daemon/src/systemd.rs | 90 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 daemon/src/systemd.rs diff --git a/daemon/src/systemd.rs b/daemon/src/systemd.rs new file mode 100644 index 00000000..d733265d --- /dev/null +++ b/daemon/src/systemd.rs @@ -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 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 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 { + 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())) +}