refactor(#2352): quota enable/limit via daemon wire commands

This commit is contained in:
damocles 2026-07-14 23:00:34 +02:00
commit 53d4f5ca32
3 changed files with 49 additions and 13 deletions

View file

@ -759,9 +759,9 @@ async fn main() -> Result<()> {
resume_session,
} => choom(&name, resume_session.as_deref()),
Cmd::Quota { cmd } => match cmd {
QuotaCmd::Enable => quota_enable().await,
QuotaCmd::Enable => quota_enable(&socket).await,
QuotaCmd::Show { name } => quota_show(name.as_deref()).await,
QuotaCmd::Limit { name, size } => quota_limit(&name, &size).await,
QuotaCmd::Limit { name, size } => quota_limit(&socket, &name, &size).await,
},
Cmd::MarkdownDocs => {
print!("{}", clap_markdown::help_markdown::<Cli>());
@ -1041,13 +1041,8 @@ fn wg_status() -> Result<()> {
}
/// `quota enable` — turn on btrfs qgroup accounting (operator opt-in).
async fn quota_enable() -> Result<()> {
hive_c0re::priv_client::ensure_btrfs_quota()
.await
.context("enable btrfs qgroup accounting")?;
println!("btrfs qgroup accounting enabled on the agent-state filesystem.");
println!("(usage may read 0 until btrfs finishes its background rescan)");
Ok(())
async fn quota_enable(socket: &Path) -> Result<()> {
daemon_request(socket, hive_host_sock::HostRequest::QuotaEnable, "quota").await
}
/// `quota show [name]` — report per-agent disk usage from btrfs qgroups.
@ -1088,11 +1083,17 @@ async fn quota_show(name: Option<&str>) -> Result<()> {
}
/// `quota limit <name> <size>` — set or clear an agent's disk quota.
async fn quota_limit(name: &str, size: &str) -> Result<()> {
async fn quota_limit(socket: &Path, name: &str, size: &str) -> Result<()> {
let limit = parse_quota_size(size)?;
hive_c0re::priv_client::set_subvolume_quota(name, limit)
.await
.with_context(|| format!("set quota for {name}"))?;
daemon_request(
socket,
hive_host_sock::HostRequest::QuotaLimit {
name: name.to_owned(),
limit,
},
"quota",
)
.await?;
match limit {
Some(n) => println!("set {name} quota to {} ({n} bytes)", human_bytes(n)),
None => println!("cleared {name} quota"),

View file

@ -199,6 +199,8 @@ async fn dispatch(req: &HostRequest, coord: Arc<Coordinator>) -> HostResponse {
HostRequest::SetAgentGithubToken { agent, token } => {
handle_set_agent_github_token(agent, token).await?
}
HostRequest::QuotaEnable => handle_quota_enable().await?,
HostRequest::QuotaLimit { name, limit } => handle_quota_limit(name, *limit).await?,
})
}
.await;
@ -408,6 +410,25 @@ async fn handle_set_agent_github_token(agent: &str, token: &str) -> Result<HostR
)]))
}
async fn handle_quota_enable() -> Result<HostResponse> {
crate::priv_client::ensure_btrfs_quota()
.await
.context("enable btrfs qgroup accounting")?;
Ok(HostResponse::messages(vec![
"btrfs qgroup accounting enabled on the agent-state filesystem.".to_owned(),
"(usage may read 0 until btrfs finishes its background rescan)".to_owned(),
]))
}
async fn handle_quota_limit(name: &str, limit: Option<u64>) -> Result<HostResponse> {
crate::priv_client::set_subvolume_quota(name, limit)
.await
.with_context(|| format!("set quota for {name}"))?;
// Bare success: the client prints the human-readable confirmation from
// the value it sent (it holds the `human_bytes` formatter).
Ok(HostResponse::success())
}
async fn handle_matrix_sync_admin() -> Result<HostResponse> {
require_matrix_present().await?;
let register_token =

View file

@ -164,6 +164,20 @@ pub enum HostRequest {
/// (inline flag or stdin); the daemon just persists it. Read live by
/// the agent's `gh` wrapper / git credential helper — no rebuild needed.
SetAgentGithubToken { agent: String, token: String },
/// Turn on btrfs qgroup accounting on the agent-state filesystem, via
/// the privileged helper. Daemon-side equivalent of `hivectl quota
/// enable`. Returns advisory lines in [`HostResponse::messages`].
QuotaEnable,
/// Set (or, with `limit = None`, clear) an agent's btrfs disk quota via
/// the privileged helper. Daemon-side equivalent of `hivectl quota
/// limit`; the size string is parsed to bytes client-side. Returns a
/// bare success — the client prints the confirmation from the value it
/// sent.
QuotaLimit {
name: String,
#[serde(default)]
limit: Option<u64>,
},
}
/// Selects which container classes a hive-wide [`HostRequest::Stop`] /