v0.5.0: slice 5 Phase B — the host-root surface (mounts + SMART + grow + destructive gate)
The privileged write surface, isolated behind a narrow, arg-validated, adversarially- tested seam (HostOps), the same discipline as the slice-4 gate. Completes slice 5. - internal/storage: HostOps seam + SudoHostOps (systemd .mount units by fs-UUID, detach, SMART, lvs) via sudoers allowlist + fixed arg vectors, no shell; NoopHostOps fallback. - validate.go: strict UUID/mount-path/device/LVM validators + in-process systemd-escape. Headline test: adversarial matrix (metacharacters/traversal/malformed) refused with zero exec. - smart.go: smartctl SATA + NVMe parse, UNKNOWN-degrade; lvs thin-pool metadata fill. - observer enrichment (Observe only): fills smart + thin-pool metadata. - watchdog: benign re-mount response off the poll path (DevicePresent probe, rate-limited). - reconcile: ActionResize (benign, grow-only) + proxmox.ResizeLXC; destructive storage ops (ClassStorageWipe/Decommission) through the slice-4 gate, target-scoped; built+tested, inert live. - --selftest=storage [-watch] live harness; configs/felhom-agent.sudoers; privileged.* knobs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -135,6 +135,25 @@ func (c *Client) SetConfig(ctx context.Context, vmid int, params map[string]stri
|
||||
return c.dataString(ctx, http.MethodPut, path, v)
|
||||
}
|
||||
|
||||
// ResizeLXC grows a guest volume via PUT /nodes/{node}/lxc/{vmid}/resize
|
||||
// (token-covered: VM.Config.Disk + Datastore.AllocateSpace). Returns the UPID.
|
||||
//
|
||||
// disk is the volume key (e.g. "rootfs", "mp0"); size is a Proxmox size string. A
|
||||
// LEADING '+' means GROW BY that amount (e.g. "+5G"); an absolute value can only ever
|
||||
// grow (Proxmox rejects a shrink for a mounted/most volumes, but the agent must NOT rely
|
||||
// on that — the reconcile layer is responsible for refusing a shrink before it reaches
|
||||
// here, since a data-losing shrink is a destructive op, not a benign resize).
|
||||
func (c *Client) ResizeLXC(ctx context.Context, vmid int, disk, size string) (string, error) {
|
||||
if vmid == 0 || disk == "" || size == "" {
|
||||
return "", fmt.Errorf("proxmox: ResizeLXC needs vmid, disk and size")
|
||||
}
|
||||
v := url.Values{}
|
||||
v.Set("disk", disk)
|
||||
v.Set("size", size)
|
||||
path := fmt.Sprintf("/nodes/%s/lxc/%d/resize", c.node, vmid)
|
||||
return c.dataString(ctx, http.MethodPut, path, v)
|
||||
}
|
||||
|
||||
// Start starts a guest via POST /nodes/{node}/lxc/{vmid}/status/start (VM.PowerMgmt).
|
||||
func (c *Client) Start(ctx context.Context, vmid int) (string, error) {
|
||||
path := fmt.Sprintf("/nodes/%s/lxc/%d/status/start", c.node, vmid)
|
||||
|
||||
Reference in New Issue
Block a user