diff options
author | Lia Lenckowski <lialenck@protonmail.com> | 2024-09-02 13:05:47 +0200 |
---|---|---|
committer | Lia Lenckowski <lialenck@protonmail.com> | 2024-09-02 13:05:47 +0200 |
commit | 0c332494968515621099273bdc2c99d5a1f6df7f (patch) | |
tree | ed6a7d88607225e38889c51236f903b6eef2e7b4 | |
parent | dbe911b3575f0370eb1e058487f83780c30a1566 (diff) | |
download | statuspage-0c332494968515621099273bdc2c99d5a1f6df7f.tar statuspage-0c332494968515621099273bdc2c99d5a1f6df7f.tar.bz2 statuspage-0c332494968515621099273bdc2c99d5a1f6df7f.tar.zst |
add systemd user units, check systemd units via dbus
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/check.rs | 46 | ||||
-rw-r--r-- | src/dbus.rs | 27 |
4 files changed, 40 insertions, 37 deletions
@@ -1745,7 +1745,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "statuspage" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "axum", @@ -1,6 +1,6 @@ [package] name = "statuspage" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] diff --git a/src/check.rs b/src/check.rs index 42812c9..b0230e8 100644 --- a/src/check.rs +++ b/src/check.rs @@ -1,5 +1,5 @@ use crate::{log::update_service, Config, Status, GLOBAL_ERROR, STATUS}; -use anyhow::{anyhow, bail, Context, Result}; +use anyhow::{anyhow, bail, Result}; use chrono::Utc; use futures::{stream::FuturesUnordered, StreamExt}; use log::info; @@ -17,10 +17,10 @@ use crate::dbus::*; pub enum Check { Systemd(String), SystemdGlobal, -// SystemdUser { -// user: String, -// name: String, -// }, + SystemdUser { + user: String, + name: String, + }, SystemdUserGlobal(String), Pacman(String), Http { @@ -83,38 +83,17 @@ impl Check { output.status.exit_ok()?; Ok(String::from_utf8(output.stdout)?) } - Check::Systemd(sname) => { - let output = Command::new("systemctl") - .arg("show") - .arg("--no-pager") - .arg(sname) - .output() - .await?; - let output = String::from_utf8(output.stdout).context("systemctl output")?; - - let mut active = ""; - let mut sub = ""; - for line in output.split("\n") { - if let Some((key, value)) = line.split_once("=") { - match key { - "ActiveState" => active = value, - "SubState" => sub = value, - _ => (), - } - } - } - let s = format!("{active} ({sub})"); - if active != "active" { - Err(anyhow!(s)) - } else { - Ok(s) - } + Check::Systemd(name) => { + check_systemd_unit(None, name).await } Check::SystemdGlobal => { check_systemd_all(None).await } - Check::SystemdUserGlobal(username) => { - check_systemd_all(Some(username)).await + Check::SystemdUser { user, name } => { + check_systemd_unit(Some(user), name).await + } + Check::SystemdUserGlobal(user) => { + check_systemd_all(Some(user)).await } Check::Shell { command, output, .. @@ -168,6 +147,7 @@ impl Check { Check::Shell { title, .. } => title.to_owned(), Check::Pacman(_) => "Installed".to_string(), Check::SystemdGlobal => "System Services".to_string(), + Check::SystemdUser { user, .. } => format!("User service for {user}"), Check::SystemdUserGlobal(username) => format!("User services for {username}"), } } diff --git a/src/dbus.rs b/src/dbus.rs index 8fd2302..d23c7b6 100644 --- a/src/dbus.rs +++ b/src/dbus.rs @@ -1,7 +1,7 @@ use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; use zbus::{ - proxy, + proxy, Proxy, zvariant::{OwnedObjectPath, Type}, Connection, connection::Builder, address::{Address, transport::{Unix, Transport, UnixSocket}}, }; @@ -31,7 +31,7 @@ struct ServiceStatus { )] trait Manager { async fn list_units(&self) -> Result<Vec<ServiceStatus>>; - async fn get_unit(&self, unit_name: String) -> Result<OwnedObjectPath>; + async fn get_unit(&self, unit_name: &str) -> Result<OwnedObjectPath>; } async fn ensure_system_conn() -> Result<Arc<Connection>> { @@ -90,3 +90,26 @@ pub(crate) async fn check_systemd_all(user: Option<&str>) -> Result<String> { Err(anyhow!("Bad services: {}", bad.join(", "))) } } + +pub(crate) async fn check_systemd_unit(user: Option<&str>, unit: &str) -> Result<String> { + let conn = match user { + None => ensure_system_conn().await, + Some(username) => ensure_user_conn(username).await, + }?; + + let manager = ManagerProxy::new(&conn).await?; + let unit_object_path = if unit.contains('.') { + manager.get_unit(unit).await + } else { + manager.get_unit(&format!("{unit}.service")).await + }?; + + let unit_proxy = Proxy::new(&conn, "org.freedesktop.systemd1", unit_object_path, "org.freedesktop.systemd1.Unit").await?; + + let substate: String = unit_proxy.get_property("SubState").await?; + if matches!(substate.as_str(), "active" | "inactive" | "plugged" | "mounted" | "dead" | "listening" | "running" | "exited" | "waiting" | "abandoned" | "elapsed") { + Ok(format!("{unit}: {substate}")) + } else { + Err(anyhow!("{unit}: {substate}")) + } +} |