aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLia Lenckowski <lialenck@protonmail.com>2024-09-02 13:05:47 +0200
committerLia Lenckowski <lialenck@protonmail.com>2024-09-02 13:05:47 +0200
commit0c332494968515621099273bdc2c99d5a1f6df7f (patch)
treeed6a7d88607225e38889c51236f903b6eef2e7b4
parentdbe911b3575f0370eb1e058487f83780c30a1566 (diff)
downloadstatuspage-0c332494968515621099273bdc2c99d5a1f6df7f.tar
statuspage-0c332494968515621099273bdc2c99d5a1f6df7f.tar.bz2
statuspage-0c332494968515621099273bdc2c99d5a1f6df7f.tar.zst
add systemd user units, check systemd units via dbus
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/check.rs46
-rw-r--r--src/dbus.rs27
4 files changed, 40 insertions, 37 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 436ce74..a5f3cf8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1745,7 +1745,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "statuspage"
-version = "0.1.0"
+version = "0.1.1"
dependencies = [
"anyhow",
"axum",
diff --git a/Cargo.toml b/Cargo.toml
index b51b08f..acfcd65 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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}"))
+ }
+}