feat: add storage info to settings page and improve NFS export handling
Backend: - Add source/used_by/available/error fields to diskUsage in system status - collectDiskUsage() now reads /proc/mounts, samba shares and NFS exports from DB - Paths are deduplicated; shared paths list all shares/exports using them - syscall.Statfs errors surface as available=false with user-facing error - collectServiceStatus made a method of Server (receiver consistency) Frontend: - Settings page now shows two cards: mount points and shared resources - Each path shows source badge (Sistema/Mount/SMB/NFS), used_by chips, progress bar - Unavailable paths show amber warning instead of progress bar - DiskUsage interface updated with new fields - NFSExport interface updated with structured fields (fsid, async, etc) - NFS page updated to use new export fields
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -86,13 +87,62 @@ func (m *Module) Apply(ctx context.Context, database *db.DB) error {
|
||||
return database.ClearDirty(ModuleName)
|
||||
}
|
||||
|
||||
// clientSpec builds the "client(opts) client(opts)" segment of an exports line.
|
||||
// If no clients are configured, it defaults to "*(opts)".
|
||||
func clientSpec(clients []string, options string) string {
|
||||
opts := strings.TrimSpace(options)
|
||||
if opts == "" {
|
||||
opts = "ro"
|
||||
func buildFlags(e db.NFSExport) string {
|
||||
parts := make([]string, 0, 8)
|
||||
if e.ReadOnly {
|
||||
parts = append(parts, "ro")
|
||||
} else {
|
||||
parts = append(parts, "rw")
|
||||
}
|
||||
if e.Async {
|
||||
parts = append(parts, "async")
|
||||
} else {
|
||||
parts = append(parts, "sync")
|
||||
}
|
||||
if e.SubtreeCheck {
|
||||
parts = append(parts, "subtree_check")
|
||||
} else {
|
||||
parts = append(parts, "no_subtree_check")
|
||||
}
|
||||
if e.RootSquash {
|
||||
parts = append(parts, "root_squash")
|
||||
} else {
|
||||
parts = append(parts, "no_root_squash")
|
||||
}
|
||||
if e.Advanced != "" && e.Advanced != "{}" {
|
||||
var adv db.NFSAdvanced
|
||||
if err := json.Unmarshal([]byte(e.Advanced), &adv); err == nil {
|
||||
if adv.AllSquash {
|
||||
parts = append(parts, "all_squash")
|
||||
} else {
|
||||
parts = append(parts, "no_all_squash")
|
||||
}
|
||||
if adv.Secure {
|
||||
parts = append(parts, "secure")
|
||||
} else {
|
||||
parts = append(parts, "insecure")
|
||||
}
|
||||
if adv.WDelay {
|
||||
parts = append(parts, "wdelay")
|
||||
} else {
|
||||
parts = append(parts, "no_wdelay")
|
||||
}
|
||||
if adv.Hide {
|
||||
parts = append(parts, "hide")
|
||||
} else {
|
||||
parts = append(parts, "nohide")
|
||||
}
|
||||
if adv.Crossmnt {
|
||||
parts = append(parts, "crossmnt")
|
||||
}
|
||||
}
|
||||
}
|
||||
parts = append(parts, fmt.Sprintf("fsid=%d", e.FSID))
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func clientSpec(clients []string, e db.NFSExport) string {
|
||||
opts := buildFlags(e)
|
||||
if len(clients) == 0 {
|
||||
return fmt.Sprintf("*(%s)", opts)
|
||||
}
|
||||
@@ -125,7 +175,7 @@ func (m *Module) renderConfig(exports []db.NFSExport) ([]byte, error) {
|
||||
for _, export := range exports {
|
||||
data.Exports = append(data.Exports, templateExport{
|
||||
Path: export.Path,
|
||||
ClientSpec: clientSpec(export.Clients, export.Options),
|
||||
ClientSpec: clientSpec(export.Clients, export),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user