Files
baby-nas/internal/storage/snapraid.go
T
darroyo 27a52d2986 feat: add mergerfs mover and snapraid integration
New 'Almacenamiento' page with:
- Auto-detection of rsync, mergerfs, snapraid binaries and mergerfs mount
- Configurable pool settings (source/dest, macOS cleanup, rsync flags)
- Mergerfs mover with dry-run preview and live SSE output streaming
- SnapRAID diff/sync/scrub/check with live SSE output
- Async job system (1 concurrent job) with SSE streaming
- Job history table

Backend:
- internal/storage/ package with capabilities, mergerfs, snapraid, jobs
- storage_config and storage_jobs DB tables (migration 0008)
- GET/PUT /api/storage/config, GET /api/storage/capabilities
- POST/GET /api/storage/jobs, GET /api/storage/jobs/{id}/stream
- Storage operations disabled when NASCTL_EXEC_SYSTEM=false

Closes #new-feature
2026-07-06 23:23:22 -04:00

71 lines
1.5 KiB
Go

package storage
import (
"fmt"
"os"
"strconv"
"strings"
)
type SnapraidConfig struct {
Content string
DataDirs []string
ParityDir string
ScrubPlan int
}
func BuildSnapraidArgs(kind string, cfg SnapraidConfig) ([]string, error) {
if cfg.Content == "" {
return nil, fmt.Errorf("snapraid content file is required")
}
args := []string{"snapraid", "-c", cfg.Content}
switch kind {
case "snapraid_diff":
args = append(args, "diff")
case "snapraid_sync":
args = append(args, "sync")
case "snapraid_scrub":
args = append(args, "scrub", "-p", strconv.Itoa(cfg.ScrubPlan))
case "snapraid_check":
args = append(args, "check")
default:
return nil, fmt.Errorf("unknown snapraid kind: %s", kind)
}
return args, nil
}
func ValidateSnapraidContent(content string) error {
if content == "" {
return fmt.Errorf("snapraid content file is required")
}
info, err := os.Stat(content)
if err != nil {
return fmt.Errorf("snapraid content %s: %w", content, err)
}
if info.IsDir() {
return fmt.Errorf("snapraid content %s: is a directory, not a file", content)
}
return nil
}
func ValidateScrubPlan(plan int) error {
if plan < 1 || plan > 99 {
return fmt.Errorf("scrub plan must be between 1 and 99, got %d", plan)
}
return nil
}
func ParseSnapraidDataDirs(raw string) []string {
if raw == "" {
return nil
}
var dirs []string
for _, d := range strings.Split(raw, ",") {
d = strings.TrimSpace(d)
if d != "" {
dirs = append(dirs, d)
}
}
return dirs
}