hive-c0re: back agent state dirs with btrfs subvolumes
Progressive enhancement: a brand-new agent's state root under /var/lib/hyperhive/agents is created as a btrfs subvolume when the host filesystem is btrfs, otherwise it falls back to a plain directory. No existing agent is auto-migrated — the new path only fires when the root does not yet exist, so plain-dir agents are left untouched until an explicit opt-in upgrade. Two new privileged ops (subvolume create/delete are root-only): EnsureAgentSubvolume statfs-gates on btrfs, creates the subvolume, and chowns it to the hive-core user so the normal state/claude/harness mkdirs succeed inside it; DeleteAgentSubvolume btrfs-subvolume-deletes the root iff it is actually a subvolume. hive-c0re calls Ensure before the per-agent dirs are created (spawn/rebuild/InitConfig) and Delete on the purge path only — destroy keeps the subvolume for revival, matching plain-dir semantics. btrfs-progs added to the hive-priv unit PATH. Per-subvolume usage accounting + optional quota is a separate follow-up.
This commit is contained in:
parent
309cdc7546
commit
1f602d5fda
9 changed files with 242 additions and 0 deletions
|
|
@ -305,6 +305,27 @@ pub async fn control_infra_container(container: &str, action: InfraAction) -> Re
|
|||
.await?)
|
||||
}
|
||||
|
||||
/// Ensure the agent's persistent state root is a btrfs subvolume when the
|
||||
/// host FS supports it (via hive-priv, which runs as root). Idempotent and
|
||||
/// progressive: a no-op when the root already exists or the FS isn't btrfs.
|
||||
/// Safe to call on every provision.
|
||||
pub async fn ensure_agent_subvolume(agent_name: &str) -> Result<()> {
|
||||
ok(call(&PrivRequest::EnsureAgentSubvolume {
|
||||
agent_name: agent_name.to_owned(),
|
||||
})
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Delete the agent's state root iff it is a btrfs subvolume (purge path
|
||||
/// only). No-op for plain dirs / missing paths — hive-c0re's own
|
||||
/// `remove_dir_all` handles those.
|
||||
pub async fn delete_agent_subvolume(agent_name: &str) -> Result<()> {
|
||||
ok(call(&PrivRequest::DeleteAgentSubvolume {
|
||||
agent_name: agent_name.to_owned(),
|
||||
})
|
||||
.await?)
|
||||
}
|
||||
|
||||
fn check(resp: PrivResponse) -> Result<(String, String)> {
|
||||
if resp.ok {
|
||||
Ok((resp.stdout, resp.stderr))
|
||||
|
|
|
|||
Loading…
Reference in a new issue