time-sync: one time daemon, timesyncd, with its servers declared
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).
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
// 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() },
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user