The second review of #147 found three blockers before the home server. 1. ${setting:} was not filled in a unit's name, so the distribution timers would have reached the machine as "zfs-scrub-weekly@${setting:scrub-pool}.timer". mesh-controller #171 fills it and refuses any value that is not a unit-name part. The module's own schedule needs no setting in a name now: the node-engine's timer for the scheduled process zfs-mesh-scrub fires `zfs-tools scrub-run` every quarter of an hour, and the run reads the pool, cadence, day and time from the configuration file. 2. The run does what upstream's zfs-scrub@.service does: if a scrub is running it waits for it with zpool wait -t scrub, otherwise it starts one and waits. It never pauses or stops a scrub, and the unit has no ExecStop. A resilver defers the scrub. The served slot is kept in /var/lib/zfs-tools. 3. Unassigning left the pool with no schedule. mesh-host #66 (hq ADR 0269, proposed) gives the distribution timer back running and enabled. The README says not to unassign before it is merged. Also: the run comes before the distribution timers in the declaration; the day and time are checked against fixed sets and reach no unit file (an invalid value runs nothing); a due scrub not started an hour after its time is a warning; the error counts outlive a restart in a small state file.
57 lines
1.9 KiB
Go
57 lines
1.9 KiB
Go
// The zfs module's Go bundle: the mesh's view of ZFS on a machine — its pools' health, layout, space,
|
|
// scrubs, I/O, cache and events, every dataset with its space and snapshots — and one act, taking a named
|
|
// snapshot of one dataset.
|
|
//
|
|
// One binary, four ways to run. With no argument it is the bundle the node's tool runner launches and
|
|
// speaks MCP to over stdio (novox/hq ADR 0188, ADR 0193), as the operator account. With `watch` and
|
|
// `events` it is one of the module's two long-running processes, run by the node-engine: the watch, which
|
|
// the health check zfs_health stands on (watch.go), and the event follower, as root, judged by its unit
|
|
// (follow.go). With `scrub-run` it is the scheduled scrub, run as root by the node-engine's timer
|
|
// (schedule.go).
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) > 1 {
|
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
|
|
defer stop()
|
|
switch os.Args[1] {
|
|
case "watch":
|
|
(&Watch{M: Here(), Out: os.Stdout}).Loop(ctx)
|
|
case "scrub-run":
|
|
said, err := Here().ScrubRun(ctx, ServedFile)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println(said)
|
|
case "events":
|
|
if err := Follower(ctx, os.Stdout); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
default:
|
|
fmt.Fprintf(os.Stderr, "zfs-tools: %q is not a way to run; with no argument it serves its tools, with watch it "+
|
|
"watches the pools, with events it follows ZFS's events, with scrub-run it runs the scheduled scrub\n", os.Args[1])
|
|
os.Exit(2)
|
|
}
|
|
return
|
|
}
|
|
m := Here()
|
|
m.Emit = func(eventType string, body any) error { return stdio.Emit(eventType, body) }
|
|
// An empty name serves as the module the runtime names (MESH_SERVED_MODULE): zfs.
|
|
if err := stdio.Serve("", Tools(m)); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|