v0.10.0: Phase B — Storage Management UI Polish & Health Severity Fix
- Health severity fix: mount-point check downgraded from issue (FAIL) to warning (WARN) - All storage health messages translated to Hungarian - Success flash messages for all storage operations - Edit storage path labels (inline edit UI + backend) - App details per storage path on settings page (expandable list with names + sizes) - Storage badge on stacks page showing which storage each app uses - Deploy dropdown with free space display and low-space warning (<20%) - Filesystem & disk info on settings page (ext4/btrfs, device, model via findmnt) - Backup page storage context with per-app storage label badges Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ package system
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -90,3 +91,52 @@ func formatGB(gb float64) string {
|
||||
}
|
||||
return fmt.Sprintf("%.1f GB", gb)
|
||||
}
|
||||
|
||||
// FSInfo holds filesystem type, device, and disk model info.
|
||||
type FSInfo struct {
|
||||
FSType string // "ext4", "btrfs"
|
||||
Device string // "/dev/sda1"
|
||||
Model string // "WD Elements 25A2" (best-effort from sysfs)
|
||||
}
|
||||
|
||||
// GetFSInfo returns filesystem info for a path using findmnt, or nil on error.
|
||||
func GetFSInfo(path string) *FSInfo {
|
||||
out, err := exec.Command("findmnt", "-n", "-o", "SOURCE,FSTYPE", "--target", path).Output()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
fields := strings.Fields(strings.TrimSpace(string(out)))
|
||||
if len(fields) < 2 {
|
||||
return nil
|
||||
}
|
||||
info := &FSInfo{
|
||||
Device: fields[0],
|
||||
FSType: fields[1],
|
||||
}
|
||||
// Try to get disk model from sysfs
|
||||
info.Model = diskModel(info.Device)
|
||||
return info
|
||||
}
|
||||
|
||||
// diskModel reads the disk model from /sys/block/<dev>/device/model.
|
||||
func diskModel(device string) string {
|
||||
// /dev/sda1 → sda, /dev/nvme0n1p1 → nvme0n1
|
||||
base := filepath.Base(device)
|
||||
// Strip partition number: sda1 → sda, nvme0n1p1 → nvme0n1
|
||||
disk := base
|
||||
if strings.HasPrefix(base, "nvme") {
|
||||
// nvme0n1p1 → find last 'p' followed by digits
|
||||
if idx := strings.LastIndex(base, "p"); idx > 4 {
|
||||
disk = base[:idx]
|
||||
}
|
||||
} else {
|
||||
// sda1 → sda: strip trailing digits
|
||||
disk = strings.TrimRight(base, "0123456789")
|
||||
}
|
||||
modelPath := "/sys/block/" + disk + "/device/model"
|
||||
data, err := os.ReadFile(modelPath)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(string(data))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user