refactor(#2352): quota show via daemon wire command

This commit is contained in:
damocles 2026-07-14 23:58:55 +02:00 committed by mara
commit 3797177e7f
3 changed files with 116 additions and 30 deletions

View file

@ -178,6 +178,35 @@ pub enum HostRequest {
#[serde(default)]
limit: Option<u64>,
},
/// Report per-agent btrfs qgroup usage (`hivectl quota show [name]`).
/// The daemon resolves the agent set (all kept state dirs when `name`
/// is absent) and reads each subvolume's referenced/exclusive usage via
/// the privileged helper. Result rows land in [`HostResponse::quota`];
/// a "btrfs quota not enabled" error short-circuits the whole sweep as a
/// plain [`HostResponse::error`] so the client can print the enable hint.
QuotaShow {
#[serde(default)]
name: Option<String>,
},
}
/// One agent's btrfs qgroup usage row — the [`HostRequest::QuotaShow`]
/// result unit. `referenced` / `exclusive` are byte counts when the agent
/// has a live qgroup; both are `None` (with an explanatory `note`) for a
/// plain-dir agent that has no subvolume to account. The client formats the
/// byte counts into human-readable columns.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QuotaRow {
pub agent: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub referenced: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub exclusive: Option<u64>,
/// Set instead of the byte counts when the agent has no qgroup data
/// (plain dir, or a non-"quota not enabled" read error), so the client
/// can print an inline explanation and keep going.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub note: Option<String>,
}
/// Selects which container classes a hive-wide [`HostRequest::Stop`] /
@ -280,6 +309,10 @@ pub struct HostResponse {
/// Empty for requests that produce no such output.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub messages: Vec<String>,
/// `QuotaShow` result — one row per agent with its btrfs qgroup usage.
/// `None` for every other request kind.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub quota: Option<Vec<QuotaRow>>,
}
impl HostResponse {
@ -369,4 +402,14 @@ impl HostResponse {
..Self::default()
}
}
/// `QuotaShow` result — one usage row per agent.
#[must_use]
pub fn quota(rows: Vec<QuotaRow>) -> Self {
Self {
ok: true,
quota: Some(rows),
..Self::default()
}
}
}