internal/router: wait ntp synced on Synology

This commit is contained in:
Cuong Manh Le
2023-08-10 20:28:29 +00:00
committed by Cuong Manh Le
parent d292e03d1b
commit 32219e7d32
5 changed files with 65 additions and 56 deletions

View File

@@ -54,7 +54,7 @@ func (d *Ddwrt) Uninstall(_ *service.Config) error {
func (d *Ddwrt) PreRun() error {
_ = d.Cleanup()
return ntp.Wait()
return ntp.WaitNvram()
}
func (d *Ddwrt) Setup() error {

View File

@@ -45,7 +45,7 @@ func (m *Merlin) Uninstall(_ *service.Config) error {
func (m *Merlin) PreRun() error {
_ = m.Cleanup()
return ntp.Wait()
return ntp.WaitNvram()
}
func (m *Merlin) Setup() error {

View File

@@ -1,16 +1,20 @@
package ntp
import (
"bytes"
"context"
"errors"
"fmt"
"os/exec"
"time"
"github.com/Control-D-Inc/ctrld/internal/router/nvram"
"tailscale.com/logtail/backoff"
"github.com/Control-D-Inc/ctrld/internal/router/nvram"
)
func Wait() error {
// WaitNvram waits NTP synced by checking "ntp_ready" value using nvram.
func WaitNvram() error {
// Wait until `ntp_ready=1` set.
b := backoff.NewBackoff("ntp.Wait", func(format string, args ...any) {}, 10*time.Second)
for {
@@ -24,3 +28,19 @@ func Wait() error {
b.BackOff(context.Background(), errors.New("ntp not ready"))
}
}
// WaitUpstart waits NTP synced by checking upstart task "ntpsync" is in "stop/waiting" state.
func WaitUpstart() error {
// Wait until `initctl status ntpsync` returns stop state.
b := backoff.NewBackoff("ntp.WaitUpstart", func(format string, args ...any) {}, 10*time.Second)
for {
out, err := exec.Command("initctl", "status", "ntpsync").CombinedOutput()
if err != nil {
return fmt.Errorf("exec.Command: %w", err)
}
if bytes.Contains(out, []byte("stop/waiting")) {
return nil
}
b.BackOff(context.Background(), errors.New("ntp not ready"))
}
}

View File

@@ -1,14 +1,21 @@
package synology
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"strings"
"time"
"github.com/Control-D-Inc/ctrld/internal/router/dnsmasq"
"github.com/kardianos/service"
"tailscale.com/logtail/backoff"
"github.com/Control-D-Inc/ctrld"
"github.com/kardianos/service"
"github.com/Control-D-Inc/ctrld/internal/router/dnsmasq"
"github.com/Control-D-Inc/ctrld/internal/router/ntp"
)
const (
@@ -19,16 +26,20 @@ const (
)
type Synology struct {
cfg *ctrld.Config
cfg *ctrld.Config
useUpstart bool
}
// New returns a router.Router for configuring/setup/run ctrld on Ubios routers.
func New(cfg *ctrld.Config) *Synology {
return &Synology{cfg: cfg}
return &Synology{
cfg: cfg,
useUpstart: service.Platform() == "linux-upstart",
}
}
func (s *Synology) ConfigureService(svc *service.Config) error {
svc.Option["UpstartScript"] = upstartScript
svc.Option["LogOutput"] = true
return nil
}
@@ -41,6 +52,12 @@ func (s *Synology) Uninstall(_ *service.Config) error {
}
func (s *Synology) PreRun() error {
if s.useUpstart {
if err := ntp.WaitUpstart(); err != nil {
return err
}
return waitDhcpServer()
}
return nil
}
@@ -88,49 +105,21 @@ func restartDNSMasq() error {
return nil
}
// Copied from https://github.com/kardianos/service/blob/6fe2824ee8248e776b0f8be39aaeff45a45a4f6c/service_upstart_linux.go#L232
// With modification to wait for dhcpserver started before ctrld.
// The upstart script should stop with an INT or the Go runtime will terminate
// the program before the Stop handler can run.
const upstartScript = `# {{.Description}}
{{if .DisplayName}}description "{{.DisplayName}}"{{end}}
{{if .HasKillStanza}}kill signal INT{{end}}
{{if .ChRoot}}chroot {{.ChRoot}}{{end}}
{{if .WorkingDirectory}}chdir {{.WorkingDirectory}}{{end}}
start on filesystem or runlevel [2345]
stop on runlevel [!2345]
start on started dhcpserver
normal exit 0 TERM HUP
{{if and .UserName .HasSetUIDStanza}}setuid {{.UserName}}{{end}}
respawn
respawn limit 10 5
umask 022
console none
pre-start script
test -x {{.Path}} || { stop; exit 0; }
end script
# Start
script
{{if .LogOutput}}
stdout_log="/var/log/{{.Name}}.out"
stderr_log="/var/log/{{.Name}}.err"
{{end}}
if [ -f "/etc/sysconfig/{{.Name}}" ]; then
set -a
source /etc/sysconfig/{{.Name}}
set +a
fi
exec {{if and .UserName (not .HasSetUIDStanza)}}sudo -E -u {{.UserName}} {{end}}{{.Path}}{{range .Arguments}} {{.|cmd}}{{end}}{{if .LogOutput}} >> $stdout_log 2>> $stderr_log{{end}}
end script
`
func waitDhcpServer() error {
// Wait until `initctl status dhcpserver` returns running state.
b := backoff.NewBackoff("waitDhcpServer", func(format string, args ...any) {}, 10*time.Second)
for {
out, err := exec.Command("initctl", "status", "dhcpserver").CombinedOutput()
if err != nil {
if strings.Contains(err.Error(), "Unknown job") {
// dhcpserver service does not exist.
return nil
}
return fmt.Errorf("exec.Command: %w", err)
}
if bytes.Contains(out, []byte("start/running")) {
return nil
}
b.BackOff(context.Background(), errors.New("ntp not ready"))
}
}

View File

@@ -49,7 +49,7 @@ func (f *FreshTomato) Uninstall(_ *service.Config) error {
func (f *FreshTomato) PreRun() error {
_ = f.Cleanup()
return ntp.Wait()
return ntp.WaitNvram()
}
func (f *FreshTomato) Setup() error {