agent v0.50.0: NAS network storage Part A1 (NFS/SMB automount foundation)
Host-side NFS/SMB automount of a bulk-media NAS share under /mnt/felhom-drives/<name> (propagates into the guest via the existing shared bind), the +100000 uid recipe, per-share liveness, and add/list/remove local-API endpoints. A NAS is a distinct class that bypasses the drive enroll/eject/decommission/SMART/watchdog machinery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxLA1mZurFq9kt8hneFeCs
This commit is contained in:
@@ -45,7 +45,7 @@ import (
|
||||
|
||||
// version is the agent version. Overridable at build time with
|
||||
// -ldflags "-X main.version=<v>"; defaults to the in-repo CHANGELOG version.
|
||||
var version = "0.49.0"
|
||||
var version = "0.50.0"
|
||||
|
||||
// runGuestHook is the PVE pre-start hook body (`felhom-agent guest-hook <vmid> <phase>`). On the
|
||||
// pre-start phase it creates placeholder dirs for any absent bind-mount source so the guest always boots
|
||||
@@ -216,7 +216,10 @@ func newProxmoxClient(cfg config.Config) (*proxmox.Client, error) {
|
||||
// every argument is validated in internal/storage before any command is built. A
|
||||
// missing/declined sudoers entry degrades per-op (SMART→UNKNOWN, mount→logged error), not a
|
||||
// crash.
|
||||
func newHostOps(cfg config.Config, logger *slog.Logger) storage.HostOps {
|
||||
// Returns the concrete *storage.SudoHostOps (not the HostOps interface) so callers that need the
|
||||
// methods outside that lean interface — the host-reboot mount re-assert and the Part-A1 network-mount
|
||||
// surface — can reach them without a type assertion. It still satisfies storage.HostOps everywhere.
|
||||
func newHostOps(cfg config.Config, logger *slog.Logger) *storage.SudoHostOps {
|
||||
mode := proxmox.RunnerMode(cfg.Privileged.Mode)
|
||||
if mode == "" {
|
||||
mode = proxmox.RunnerSudo
|
||||
@@ -549,7 +552,7 @@ func runDaemon(cfg config.Config, logger *slog.Logger) int {
|
||||
// re-enumeration can move the device (/dev/sdb→sdc); ReassertEnrolledMounts re-resolves each by
|
||||
// filesystem UUID and re-mounts (idempotent `enable --now`) so a letter reshuffle is a no-op.
|
||||
// Type-asserted (the concrete op exposes it; the interface stays lean).
|
||||
mountReasserter, _ := hostOps.(*storage.SudoHostOps)
|
||||
mountReasserter := hostOps // concrete *storage.SudoHostOps — exposes ReassertEnrolledMounts
|
||||
if mountReasserter != nil {
|
||||
mountReasserter.ReassertEnrolledMounts(ctx)
|
||||
}
|
||||
@@ -699,7 +702,7 @@ func buildRestoreTestScheduler(cfg config.Config, px *proxmox.Client, engine *re
|
||||
// leaf (stable fingerprint). Any failure DISABLES the server (returns nil) WITHOUT crashing the
|
||||
// daemon — the host still reports/reconciles; only the controller channel is unavailable until
|
||||
// fixed. The opened token store is returned via outTokens so the caller can Close it.
|
||||
func buildLocalAPIServer(cfg config.Config, px *proxmox.Client, store *backup.Store, observer *storage.Observer, hostOps storage.HostOps, gate *reconcile.Gate, collector *hub.Collector, intent localapi.IntentRecorder, guestBinds *localapi.GuestBindStore, formatJobs *localapi.FormatJobStore, logger *slog.Logger, outTokens **localapi.TokenStore) *localapi.Server {
|
||||
func buildLocalAPIServer(cfg config.Config, px *proxmox.Client, store *backup.Store, observer *storage.Observer, hostOps *storage.SudoHostOps, gate *reconcile.Gate, collector *hub.Collector, intent localapi.IntentRecorder, guestBinds *localapi.GuestBindStore, formatJobs *localapi.FormatJobStore, logger *slog.Logger, outTokens **localapi.TokenStore) *localapi.Server {
|
||||
if !cfg.LocalAPI.Enabled() {
|
||||
return nil
|
||||
}
|
||||
@@ -751,6 +754,9 @@ func buildLocalAPIServer(cfg config.Config, px *proxmox.Client, store *backup.St
|
||||
DiskGate: storageGateAdapter{gate: gate, hostID: cfg.Hub.HostID},
|
||||
Guests2: px,
|
||||
GuestAttach: guestBinder, // slice 10 P2: bind enrolled data drives into the guest
|
||||
// Network storage (NAS) — Part A1: the privileged host network-mount surface (NFS/SMB automount).
|
||||
NetStorage: hostOps,
|
||||
SmbCredsDir: cfg.Privileged.SmbCredsDir,
|
||||
ControllerSwap: guestBinder, // Phase 1: agentic controller update — in-guest image swap
|
||||
// F2-b: recover a guest left with a stale vzdump lock by a reboot-during-backup. Reads + start
|
||||
// go through the API client; the `pct unlock` is the one fenced root-CLI op (no API equivalent).
|
||||
|
||||
Reference in New Issue
Block a user