Three machines ran timesyncd and one ran ntpd. The module declares timesyncd running with a 50-mesh.conf drop-in (European pool) and ntp absent (hq ADR 0180). A run-once step of its Go binary stops and disables ntpd first and takes out only dangling wants-links, so removing the package leaves no enabled unit pointing at nothing. A provider's drop-in sorting after the mesh's still wins and is reported, not removed. Tools: time_sync_status, _servers, _sync_now (to-be 42 Phase 1).
78 lines
2.7 KiB
Go
78 lines
2.7 KiB
Go
// time-sync's tools bundle (novox/hq to-be 42 Phase 1, research 026/05), and its step.
|
|
//
|
|
// Served by the node's runtime over MCP on stdio through the Go SDK (ADR 0188, ADR 0193) when it is
|
|
// started with no arguments. Started as `time-sync-tools retire <unit>…` it is the module's step,
|
|
// which the host runs once as root for every version of the bundle (timesync.go says why).
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
)
|
|
|
|
// binaryName is what the build names this bundle's executable: the manifest's `binary`.
|
|
const binaryName = "time-sync-tools"
|
|
|
|
func bg() context.Context { return context.Background() }
|
|
|
|
func main() {
|
|
m := ThisMachine()
|
|
if len(os.Args) > 1 {
|
|
if os.Args[1] != "retire" || len(os.Args) < 3 {
|
|
fmt.Fprintf(os.Stderr, "usage: %s [retire <unit>…]\n", binaryName)
|
|
os.Exit(2)
|
|
}
|
|
r, err := m.Retire(os.Args[2:], Wants, Dangling, os.Remove)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Printf("disabled: %s; dangling links taken out: %s\n", orNone(r.Disabled), orNone(r.Removed))
|
|
return
|
|
}
|
|
// An empty name serves as the module the runtime names (MESH_SERVED_MODULE): time-sync.
|
|
if err := stdio.Serve("", tools(m)); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func orNone(list []string) string {
|
|
if len(list) == 0 {
|
|
return "none"
|
|
}
|
|
return strings.Join(list, ", ")
|
|
}
|
|
|
|
func tools(m *Machine) []stdio.Tool {
|
|
return []stdio.Tool{
|
|
{
|
|
Name: "time_sync_status",
|
|
Description: "Whether the clock is synchronised and how well: NTP on, synchronised, timesyncd's unit state, the server " +
|
|
"it uses, offset, delay and jitter in milliseconds, stratum and packet count (timedatectl timesync-status, with " +
|
|
"its every line), and any other time daemon installed beside it. timesyncd not answering is said, not failed.",
|
|
Input: schema(map[string]any{}),
|
|
Run: func(map[string]any) (any, error) { return m.Status() },
|
|
},
|
|
{
|
|
Name: "time_sync_servers",
|
|
Description: "The servers timesyncd uses (the one now, the configured, the fallback, the link's and the runtime's) " +
|
|
"and every configuration file in the order it reads them with the NTP= and FallbackNTP= each sets; which file " +
|
|
"decides, and a note when a drop-in sorting after the mesh's wins.",
|
|
Input: schema(map[string]any{}),
|
|
Run: func(map[string]any) (any, error) { return m.Servers() },
|
|
},
|
|
{
|
|
Name: "time_sync_sync_now",
|
|
Description: "Restart timesyncd (sudo -n), which asks its server at once, and answer the status after up to ten " +
|
|
"seconds of waiting for its first packet.",
|
|
Input: schema(map[string]any{}),
|
|
Run: func(map[string]any) (any, error) { return m.SyncNow() },
|
|
},
|
|
}
|
|
}
|