fix: populate fsid for legacy NFS exports on migration

Migration 0002 added fsid column with DEFAULT 0 but never
populated existing rows. Now PopulateLegacyFSIDs() runs after 0002
to extract fsid from legacy options string or generate random.

Also: move generateRandomFSID to internal/system to avoid import
cycles. Migration 0004 drops the legacy options column.

Version: 0.3.1 -> 0.3.2
This commit is contained in:
2026-07-06 01:22:16 -04:00
parent b678c8e1a9
commit 0da789cd96
8 changed files with 94 additions and 25 deletions
+56
View File
@@ -3,6 +3,10 @@ package db
import (
"database/sql"
"fmt"
"regexp"
"strconv"
"github.com/darroyo/nasctl/internal/system"
)
func scanNFSExport(row interface {
@@ -199,3 +203,55 @@ func (d *DB) FSIDExists(fsid int64) (bool, error) {
}
return count > 0, nil
}
var fsidLegacyPattern = regexp.MustCompile(`fsid=(\d+)`)
func (d *DB) PopulateLegacyFSIDs() error {
rows, err := d.conn.Query(`SELECT id, fsid, options FROM nfs_exports WHERE fsid = 0`)
if err != nil {
return fmt.Errorf("query legacy fsids: %w", err)
}
defer rows.Close()
type pending struct {
id int64
fsid int64
}
var updates []pending
for rows.Next() {
var id, fsid int64
var options string
if err := rows.Scan(&id, &fsid, &options); err != nil {
return fmt.Errorf("scan row: %w", err)
}
newFSID := int64(0)
if m := fsidLegacyPattern.FindStringSubmatch(options); m != nil {
if n, err := strconv.ParseInt(m[1], 10, 64); err == nil && n > 0 {
newFSID = n
}
}
if newFSID == 0 {
n, err := system.GenerateRandomFSID()
if err != nil {
return fmt.Errorf("generate fsid: %w", err)
}
newFSID = int64(n)
}
updates = append(updates, pending{id, newFSID})
}
if err := rows.Err(); err != nil {
return fmt.Errorf("rows iteration: %w", err)
}
for _, u := range updates {
if _, err := d.conn.Exec(`UPDATE nfs_exports SET fsid = ? WHERE id = ?`, u.fsid, u.id); err != nil {
return fmt.Errorf("update fsid for id %d: %w", u.id, err)
}
}
return nil
}