fix(dashboard): correct container-load cgroup path (always-empty LOAD tab)
The dashboard LOAD tab always showed "no running agent containers": container_stats::gather() looked for each agent's cgroup at machine.slice/machine-h\x2d<name>.scope, but that path never exists. nixos-container runs `systemd-nspawn --keep-unit` with `Slice = "machine.slice"` (nixpkgs virtualisation/nixos-containers.nix), so --keep-unit means no separate machined `machine-<name>.scope` is created — the container's cgroup IS the launching service unit, `container@<machine>.service`, under machine.slice. systemd-machined still logs "New machine <name>" (registration), which is what made the scope-path assumption look plausible, but the cgroup stays on the unit. Fix scope_dir to machine.slice/container@<machine>.service and drop the \x2d escaping (the service unit name is used verbatim in the cgroup dir; the journal shows the literal `container@h-<agent>.service`). Adds a unit test pinning the path.
This commit is contained in:
parent
878f95205b
commit
6c3a83ffa1
1 changed files with 41 additions and 10 deletions
|
|
@ -3,7 +3,11 @@
|
|||
//! machine directly — same privsep-clean posture as the turn-stats
|
||||
//! sqlite reads (`cpu.stat` / `memory.*` are world-readable; no
|
||||
//! `hive-priv` needed). Runs host-side in hive-c0re, where
|
||||
//! `/sys/fs/cgroup/machine.slice/` holds the nspawn machine scopes.
|
||||
//! `/sys/fs/cgroup/machine.slice/` holds the per-container cgroups. Because
|
||||
//! nixos-container runs `systemd-nspawn --keep-unit` (with
|
||||
//! `Slice = "machine.slice"`), each container's cgroup is its launching
|
||||
//! service unit `container@<machine>.service` — not a machined
|
||||
//! `machine-<name>.scope`. See [`scope_dir`].
|
||||
//!
|
||||
//! No network: agents share the host network namespace
|
||||
//! (`privateNetwork = false`), so there is no per-container net
|
||||
|
|
@ -47,16 +51,22 @@ pub struct ContainerResource {
|
|||
pub mem_max_bytes: Option<u64>,
|
||||
}
|
||||
|
||||
/// systemd escapes the machine name in the cgroup scope dir
|
||||
/// (`machine-<escaped>.scope`). For our machine names — `h-<agent>`,
|
||||
/// agent ∈ `[a-z0-9_-]` — the only character systemd escapes is `-`,
|
||||
/// which becomes `\x2d` (verified against `systemd-escape`).
|
||||
fn escape_machine(machine: &str) -> String {
|
||||
machine.replace('-', "\\x2d")
|
||||
}
|
||||
|
||||
/// Cgroup directory for a container's machine.
|
||||
///
|
||||
/// nixos-container runs `systemd-nspawn --keep-unit` with
|
||||
/// `Slice = "machine.slice"` (see nixpkgs
|
||||
/// `virtualisation/nixos-containers.nix`). `--keep-unit` means nspawn does
|
||||
/// **not** create a separate machined `machine-<name>.scope` — the
|
||||
/// container's cgroup *is* the launching service unit,
|
||||
/// `container@<machine>.service`, placed under `machine.slice`.
|
||||
/// systemd-machined still logs "New machine <name>" (registration), but the
|
||||
/// cgroup stays on the service unit. So the path is
|
||||
/// `machine.slice/container@<machine>.service`, and the service unit name is
|
||||
/// used verbatim — no `\x2d` escaping (that only applies when a string is
|
||||
/// converted *into* a scope/slice unit name, not to an already-formed
|
||||
/// instance unit; the journal shows the literal `container@h-<agent>.service`).
|
||||
fn scope_dir(machine: &str) -> PathBuf {
|
||||
PathBuf::from(MACHINE_SLICE).join(format!("machine-{}.scope", escape_machine(machine)))
|
||||
PathBuf::from(MACHINE_SLICE).join(format!("container@{machine}.service"))
|
||||
}
|
||||
|
||||
/// Read a single unsigned integer from a one-line cgroup file.
|
||||
|
|
@ -175,3 +185,24 @@ pub async fn gather() -> Vec<ContainerResource> {
|
|||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn scope_dir_is_the_keep_unit_service_under_machine_slice() {
|
||||
// nixos-container `--keep-unit` keeps the cgroup on the service
|
||||
// unit `container@<machine>.service` (literal name, no `\x2d`),
|
||||
// under machine.slice — NOT a machined `machine-<name>.scope`.
|
||||
assert_eq!(
|
||||
scope_dir("h-atlas"),
|
||||
PathBuf::from("/sys/fs/cgroup/machine.slice/container@h-atlas.service")
|
||||
);
|
||||
// Underscores in agent names are likewise verbatim.
|
||||
assert_eq!(
|
||||
scope_dir("h-foo_bar"),
|
||||
PathBuf::from("/sys/fs/cgroup/machine.slice/container@h-foo_bar.service")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue