d2071430ea
Tier 2 rsync-mirrors each HDD app's recovery unit + appdata to a DIFFERENT physical disk (the only off-drive protection bind-mounted userdata can get; PBS can't reach it). Auto-enabled, auto-target: prefer another registered drive (different physical disk via system.SamePhysicalDevice), else the internal SSD for SMALL units only — with a size-aware headroom guard that REFUSES rather than fill the ~8G guest rootfs, recording an honest "needs 2nd HDD" status. Status persisted via the surviving CrossDriveBackup; "2. mentés" UI card now populated. Daily tier2-backup job + POST /api/backup/tier2. - backup/tier2.go (engine+selection+headroom), tier2_test.go (headroom arithmetic) - system.SamePhysicalDevice (linux Stat_t.Dev + stub) - handlers.go Tier2 UI population + tier2DestLabel; backups.html honest no-target reason - fixed stale TestBackupCopiesOnPath (old felhom-data layout -> in-guest layout) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
113 lines
2.8 KiB
Go
113 lines
2.8 KiB
Go
//go:build !linux
|
|
|
|
package system
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// IsMountPoint always returns true on non-Linux (assume OK for dev/testing).
|
|
func IsMountPoint(_ string) bool { return true }
|
|
|
|
// IsWritable checks if the given path is writable by attempting to create+remove a temp file.
|
|
func IsWritable(path string) bool {
|
|
testFile := filepath.Join(path, ".felhom-write-test")
|
|
f, err := os.Create(testFile)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
f.Close()
|
|
os.Remove(testFile)
|
|
return true
|
|
}
|
|
|
|
// PathsOverlap returns true if one path is a parent or child of the other.
|
|
func PathsOverlap(a, b string) bool {
|
|
a = filepath.Clean(a)
|
|
b = filepath.Clean(b)
|
|
if a == b {
|
|
return true
|
|
}
|
|
aSep := a + string(os.PathSeparator)
|
|
bSep := b + string(os.PathSeparator)
|
|
return strings.HasPrefix(aSep, bSep) || strings.HasPrefix(bSep, aSep)
|
|
}
|
|
|
|
// DiskUsageInfo holds disk usage statistics for a path.
|
|
type DiskUsageInfo struct {
|
|
TotalGB float64
|
|
UsedGB float64
|
|
AvailGB float64
|
|
UsedPercent float64
|
|
TotalHuman string
|
|
UsedHuman string
|
|
}
|
|
|
|
// GetDiskUsage returns nil on non-Linux.
|
|
func GetDiskUsage(_ string) *DiskUsageInfo { return nil }
|
|
|
|
// SamePhysicalDevice always returns false on non-Linux (dev/testing only — Tier 2 runs on Linux).
|
|
func SamePhysicalDevice(_, _ string) bool { return false }
|
|
|
|
// FSInfo holds filesystem type, device, and disk model info.
|
|
type FSInfo struct {
|
|
FSType string
|
|
Device string
|
|
Model string
|
|
}
|
|
|
|
// GetFSInfo returns nil on non-Linux.
|
|
func GetFSInfo(_ string) *FSInfo { return nil }
|
|
|
|
// DestinationHealth holds the result of a tiered backup destination check.
|
|
type DestinationHealth struct {
|
|
Exists bool
|
|
Writable bool
|
|
MountPoint bool
|
|
SystemDrive bool
|
|
UsedPercent float64
|
|
FreeGB float64
|
|
Warning string
|
|
Blocked bool
|
|
Severity string
|
|
}
|
|
|
|
// CheckBackupDestination always returns ok on non-Linux (assume healthy for dev/testing).
|
|
func CheckBackupDestination(path string) DestinationHealth {
|
|
return DestinationHealth{
|
|
Exists: true,
|
|
Writable: true,
|
|
MountPoint: true,
|
|
Severity: "ok",
|
|
}
|
|
}
|
|
|
|
// ProbeStatus represents the result of a storage path probe.
|
|
type ProbeStatus int
|
|
|
|
const (
|
|
ProbeConnected ProbeStatus = iota
|
|
ProbeDisconnected
|
|
ProbeTimeout
|
|
)
|
|
|
|
// ProbeResult holds the outcome of a storage path probe.
|
|
type ProbeResult struct {
|
|
Status ProbeStatus
|
|
Err error
|
|
}
|
|
|
|
// ProbeStoragePath always returns connected on non-Linux.
|
|
func ProbeStoragePath(_ string) ProbeResult { return ProbeResult{Status: ProbeConnected} }
|
|
|
|
// IsUSBDevice always returns false on non-Linux.
|
|
func IsUSBDevice(_ string) bool { return false }
|
|
|
|
// ParseFstabUUID always returns empty on non-Linux.
|
|
func ParseFstabUUID(_, _ string) string { return "" }
|
|
|
|
// HasFelhomRawMount always returns false on non-Linux.
|
|
func HasFelhomRawMount(_, _ string) (string, bool) { return "", false }
|