all: wait NTP synced on Merlin

On some Merlin routers, the time is broken when system reboot, and need
to wait for NTP synced to get the correct time. For fetching API in cd
mode successfully, ctrld need to wait until NTP set the time correctly,
otherwise, the certificate validation would complain.
This commit is contained in:
Cuong Manh Le
2023-05-09 23:11:53 +07:00
committed by Cuong Manh Le
parent d75f871541
commit 9689607409
2 changed files with 57 additions and 0 deletions

View File

@@ -173,6 +173,13 @@ func initCLI() {
// Log config do not have thing to validate, so it's safe to init log here,
// so it's able to log information in processCDFlags.
initLogging()
if setupRouter {
if err := router.PreStart(); err != nil {
mainLog.Fatal().Err(err).Msg("failed to perform router pre-start check")
}
}
processCDFlags()
if err := ctrld.ValidateConfig(validator.New(), &cfg); err != nil {
mainLog.Fatal().Msgf("invalid config: %v", err)

View File

@@ -2,14 +2,18 @@ package router
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"sync"
"sync/atomic"
"time"
"github.com/fsnotify/fsnotify"
"github.com/kardianos/service"
"tailscale.com/logtail/backoff"
"github.com/Control-D-Inc/ctrld"
)
@@ -89,6 +93,52 @@ func ConfigureService(sc *service.Config) error {
return nil
}
// PreStart blocks until the router is ready for running ctrld.
func PreStart() (err error) {
if Name() != DDWrt {
return nil
}
pidFile := "/tmp/ctrld.pid"
// On Merlin, NTP may out of sync, so waiting for it to be ready.
//
// Remove pid file and trigger dnsmasq restart, so NTP can resolve
// server name and perform time synchronization.
pid, err := os.ReadFile(pidFile)
if err != nil {
return fmt.Errorf("PreStart: os.Readfile: %w", err)
}
if err := os.Remove(pidFile); err != nil {
return fmt.Errorf("PreStart: os.Remove: %w", err)
}
defer func() {
if werr := os.WriteFile(pidFile, pid, 0600); werr != nil {
err = errors.Join(err, werr)
return
}
if rerr := merlinRestartDNSMasq(); rerr != nil {
err = errors.Join(err, rerr)
return
}
}()
if err := merlinRestartDNSMasq(); err != nil {
return fmt.Errorf("PreStart: merlinRestartDNSMasq: %w", err)
}
// Wait until `ntp_read=1` set.
b := backoff.NewBackoff("PreStart", func(format string, args ...any) {}, 10*time.Second)
for {
out, err := nvram("get", "ntp_ready")
if err != nil {
return fmt.Errorf("PreStart: nvram: %w", err)
}
if out == "1" {
return nil
}
b.BackOff(context.Background(), errors.New("ntp not ready"))
}
}
// PostInstall performs task after installing ctrld on router.
func PostInstall() error {
name := Name()