talos/internal/pkg/timex/timex.go
Andrey Smirnov 2ea20f598a feat: replace timed with time sync controller
This is a complete rewrite of time sync process.

Now the time sync process starts early at boot time, and it adapts to
configuration changes:

* before config is available, `pool.ntp.org` is used
* once config is available, configured time servers are used

Controller updates same time sync resource as other controllers had
dependency on, so they have a chance to wait for the time sync event.

Talos services which depend on time now wait on same resource instead of
waiting on timed health.

New features:

* time sync now sticks to the particular time server unless there's an
error from that server, and server is changed in that case, this
improves time sync accuracy

* time sync acts on config changes immediately, so it's possible to
reconfigure time sync at any time

* there's a new 'epoch' field in time sync resources which allows
time-dependent controllers to regenerate certs when there's a big enough
jump in time

Features to implement later:

* apid shouldn't depend on timed, it should be started early and it
should regenerate certs on time jump

* trustd should be updated in same way

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
2021-03-29 09:29:43 -07:00

109 lines
2.9 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package timex provides a simple wrapper around adjtimex syscall.
package timex
import (
"strings"
"syscall"
)
// Values for timex.mode.
//
//nolint:golint,stylecheck,revive
const (
ADJ_OFFSET = 0x0001
ADJ_FREQUENCY = 0x0002
ADJ_MAXERROR = 0x0004
ADJ_ESTERROR = 0x0008
ADJ_STATUS = 0x0010
ADJ_TIMECONST = 0x0020
ADJ_TAI = 0x0080
ADJ_SETOFFSET = 0x0100
ADJ_MICRO = 0x1000
ADJ_NANO = 0x2000
ADJ_TICK = 0x4000
)
// Status is bitmask field of statuses.
type Status int32
// Clock statuses.
//
//nolint:golint,stylecheck,revive
const (
STA_PLL = 0x0001 /* enable PLL updates (rw) */
STA_PPSFREQ = 0x0002 /* enable PPS freq discipline (rw) */
STA_PPSTIME = 0x0004 /* enable PPS time discipline (rw) */
STA_FLL = 0x0008 /* select frequency-lock mode (rw) */
STA_INS = 0x0010 /* insert leap (rw) */
STA_DEL = 0x0020 /* delete leap (rw) */
STA_UNSYNC = 0x0040 /* clock unsynchronized (rw) */
STA_FREQHOLD = 0x0080 /* hold frequency (rw) */
STA_PPSSIGNAL = 0x0100 /* PPS signal present (ro) */
STA_PPSJITTER = 0x0200 /* PPS signal jitter exceeded (ro) */
STA_PPSWANDER = 0x0400 /* PPS signal wander exceeded (ro) */
STA_PPSERROR = 0x0800 /* PPS signal calibration error (ro) */
STA_CLOCKERR = 0x1000 /* clock hardware fault (ro) */
STA_NANO = 0x2000 /* resolution (0 = us, 1 = ns) (ro) */
STA_MODE = 0x4000 /* mode (0 = PLL, 1 = FLL) (ro) */
STA_CLK = 0x8000 /* clock source (0 = A, 1 = B) (ro) */
)
func (status Status) String() string {
var labels []string
for bit, label := range map[Status]string{
STA_PLL: "STA_PLL",
STA_PPSFREQ: "STA_PPSFREQ",
STA_PPSTIME: "STA_PPSTIME",
STA_FLL: "STA_FLL",
STA_INS: "STA_INS",
STA_DEL: "STA_DEL",
STA_UNSYNC: "STA_UNSYNC",
STA_FREQHOLD: "STA_FREQHOLD",
STA_PPSSIGNAL: "STA_PPSSIGNAL",
STA_PPSJITTER: "STA_PPSJITTER",
STA_PPSWANDER: "STA_PPSWANDER",
STA_PPSERROR: "STA_PPSERROR",
STA_CLOCKERR: "STA_CLOCKERR",
STA_NANO: "STA_NANO",
STA_MODE: "STA_MODE",
STA_CLK: "STA_CLK",
} {
if (status & bit) == bit {
labels = append(labels, label)
}
}
return strings.Join(labels, " | ")
}
// State is clock state.
type State int
// Clock states.
//
//nolint:golint,stylecheck,revive
const (
TIME_OK State = iota
TIME_INS
TIME_DEL
TIME_OOP
TIME_WAIT
TIME_ERROR
)
func (state State) String() string {
return [...]string{"TIME_OK", "TIME_INS", "TIME_DEL", "TIME_OOP", "TIME_WAIT", "TIME_ERROR"}[int(state)]
}
// Adjtimex provides a wrapper around syscall.Adjtimex.
func Adjtimex(buf *syscall.Timex) (state State, err error) {
st, err := syscall.Adjtimex(buf)
return State(st), err
}