systemd: parse static machines list, render placeholders (step 3)

This commit is contained in:
Damocles 2026-05-07 20:00:39 +02:00
parent 3fb9a36f3b
commit 6224d86965
3 changed files with 68 additions and 2 deletions

View file

@ -101,9 +101,10 @@ pub mod qobject {
#[qproperty(bool, dock_applet_mpris, cxx_name = "dockAppletMpris")]
#[qproperty(bool, dock_applet_notifications, cxx_name = "dockAppletNotifications")]
#[qproperty(bool, dock_applet_power, cxx_name = "dockAppletPower")]
// Unified systemd bar module (covers local + nspawn containers, and later remotes).
// Unified systemd bar module (covers local + nspawn containers + remotes).
#[qproperty(bool, systemd_enable, cxx_name = "systemdEnable")]
#[qproperty(i32, systemd_interval, cxx_name = "systemdInterval")]
#[qproperty(QList_QString, systemd_machines, cxx_name = "systemdMachines")]
type ModulesService = super::ModulesServiceRust;
}
@ -443,6 +444,34 @@ mod data {
}
}
// Systemd-bar group: enable + poll interval + remote SSH targets. Each
// `machines` entry is a string like "host" or "user@host"; the local
// machine is deduped by hostname even if listed.
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Systemd {
#[serde(default = "t")]
pub enable: bool,
#[serde(default = "Systemd::d_interval")]
pub interval: i32,
#[serde(default)]
pub machines: Vec<String>,
}
impl Systemd {
fn d_interval() -> i32 {
15_000
}
}
impl Default for Systemd {
fn default() -> Self {
Self {
enable: true,
interval: Self::d_interval(),
machines: Vec::new(),
}
}
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct StatsDaemon {
@ -518,7 +547,7 @@ mod data {
#[serde(default)]
pub dock: Dock,
#[serde(default)]
pub systemd: WithInterval,
pub systemd: Systemd,
#[serde(default)]
pub stats_daemon: StatsDaemon,
}
@ -595,6 +624,7 @@ pub struct ModulesServiceRust {
dock_applet_power: bool,
systemd_enable: bool,
systemd_interval: i32,
systemd_machines: QList<QString>,
}
impl Default for ModulesServiceRust {
@ -678,6 +708,13 @@ impl ModulesServiceRust {
dock_applet_power: d.dock.applets.power,
systemd_enable: d.systemd.enable,
systemd_interval: d.systemd.interval,
systemd_machines: {
let mut list = QList::<QString>::default();
for s in &d.systemd.machines {
list.append(QString::from(s.as_str()));
}
list
},
}
}
}
@ -691,6 +728,10 @@ pub(crate) fn config_path(file: &str) -> PathBuf {
base.join("nova-shell").join(file)
}
pub(crate) fn load_systemd_machines() -> Vec<String> {
load_modules_data().systemd.machines
}
fn load_modules_data() -> ModulesData {
let path = config_path("modules.json");
let raw = match std::fs::read_to_string(&path) {

View file

@ -6,6 +6,7 @@
// to require QuickControls2.prl files that nixpkgs strips. Switch to
// QList<QVariantMap> when a release ships with both fixes.
use crate::modules_service;
use core::pin::Pin;
use cxx_qt_lib::QString;
use serde::Serialize;
@ -270,6 +271,28 @@ impl qobject::SystemdService {
});
}
// Configured remote machines (placeholders; transport lands in step 4).
// Dedup local: drop entries matching the local hostname or `localhost`,
// with or without a `user@` prefix.
let host = read_hostname();
let cfg_machines = modules_service::load_systemd_machines();
for target in cfg_machines {
let host_part = target.rsplit_once('@').map_or(target.as_str(), |(_, h)| h);
if host_part == host || host_part == "localhost" {
continue;
}
all_machines.push(MachineJson {
name: target.clone(),
is_local: false,
marker: String::new(),
system_state: "pending".into(),
running_count: 0,
total_count: 0,
failed_units: Vec::new(),
running_units: Vec::new(),
});
}
let machines_json = serde_json::to_string(&all_machines).unwrap_or_else(|_| "[]".into());
self.as_mut().set_failed_count(local_failed_count);