hive-c0re: hivectl subvol upgrade — migrate an agent state dir to a btrfs subvolume
New agents get a btrfs subvolume state root automatically when the host FS is btrfs, but agents that predate that migration are left on plain dirs and miss the subvolume feature set (snapshots, per-subvol usage/quota, send/receive migration). Add an opt-in operator verb to convert an existing plain-dir agent in place. btrfs cannot promote a directory to a subvolume in place, so the new privileged op stages a sibling subvolume mirroring the dir (create + `cp -a --reflink=auto` preserving ownership/permissions/xattrs + match the root's owner and mode), then atomically renames the original aside and the subvolume into place, then removes the original. Any failure before the swap leaves the original untouched; idempotent (no-op if already a subvolume) and btrfs-gated. The `hivectl subvol upgrade <agent> --yes` verb composes it client-side like `restart`: stop the agent so its state bind-mount is released, run the migration via hive-priv, then restart it — the restart is attempted regardless of the migration outcome so a failed migration never leaves the agent down. - hive-sh4re: UpgradeAgentSubvolume priv request variant. - hive-priv: the migration handler plus stage/cleanup helpers. - hive-c0re: priv_client wrapper and the hivectl verb; regen CLI docs.
This commit is contained in:
parent
2966f682ce
commit
6b1dbebe5a
5 changed files with 351 additions and 0 deletions
|
|
@ -368,6 +368,22 @@ pub async fn set_subvolume_quota(agent_name: &str, limit_bytes: Option<u64>) ->
|
|||
.await?)
|
||||
}
|
||||
|
||||
/// Convert an existing plain-dir agent state root into a btrfs subvolume in
|
||||
/// place (operator opt-in; via hive-priv as root). The caller must stop the
|
||||
/// agent first (so its state bind-mount is gone) and restart it after.
|
||||
/// Idempotent: a no-op when the root is already a subvolume.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns an error if the hive-priv call fails, the state dir is missing,
|
||||
/// the FS isn't btrfs, or the migration (subvolume create / copy / swap)
|
||||
/// fails — in which case the original dir is left untouched.
|
||||
pub async fn upgrade_agent_subvolume(agent_name: &str) -> Result<()> {
|
||||
ok(call(&PrivRequest::UpgradeAgentSubvolume {
|
||||
agent_name: agent_name.to_owned(),
|
||||
})
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Parse `(referenced, exclusive)` bytes from `btrfs qgroup show -f --raw`
|
||||
/// output (a qgroup row is `<id-with-slash> <rfer> <excl> …`).
|
||||
///
|
||||
|
|
|
|||
Loading…
Reference in a new issue