| // Package time implements a supervisor runnable which is responsible for | 
 | // keeping both the system clock and the RTC accurate. | 
 | // Metropolis nodes need accurate time both for themselves (for log | 
 | // timestamping, validating certain certificates, ...) as well as workloads | 
 | // running on top of it expecting accurate time. | 
 | // This initial implementation is very minimalistic, running just a stateless | 
 | // NTP client per node for the whole lifecycle of it. | 
 | // This implementation is simple, but is fairly unsafe as NTP by itself does | 
 | // not offer any cryptography, so it's easy to tamper with the responses. | 
 | // See #73 for further work in that direction. | 
 | package time | 
 |  | 
 | import ( | 
 | 	"context" | 
 | 	"fmt" | 
 | 	"os/exec" | 
 | 	"strconv" | 
 | 	"strings" | 
 |  | 
 | 	"source.monogon.dev/metropolis/node" | 
 | 	"source.monogon.dev/metropolis/pkg/fileargs" | 
 | 	"source.monogon.dev/metropolis/pkg/supervisor" | 
 | ) | 
 |  | 
 | // Service implements the time service. See package documentation for further | 
 | // information. | 
 | type Service struct{} | 
 |  | 
 | func New() *Service { | 
 | 	return &Service{} | 
 | } | 
 |  | 
 | func (s *Service) Run(ctx context.Context) error { | 
 | 	// TODO(#72): Apply for a NTP pool vendor zone | 
 | 	config := strings.Join([]string{ | 
 | 		"pool ntp.monogon.dev iburst", | 
 | 		"bindcmdaddress /", | 
 | 		"stratumweight 0.01", | 
 | 		"leapsecmode slew", | 
 | 		"maxslewrate 10000", | 
 | 		"makestep 2.0 3", | 
 | 		"rtconutc", | 
 | 		"rtcsync", | 
 | 	}, "\n") | 
 | 	args, err := fileargs.New() | 
 | 	if err != nil { | 
 | 		return fmt.Errorf("cannot create fileargs: %w", err) | 
 | 	} | 
 | 	defer args.Close() | 
 | 	cmd := exec.Command( | 
 | 		"/time/chrony", | 
 | 		"-d", | 
 | 		"-i", strconv.Itoa(node.TimeUid), | 
 | 		"-g", strconv.Itoa(node.TimeUid), | 
 | 		"-f", args.ArgPath("chrony.conf", []byte(config)), | 
 | 	) | 
 | 	cmd.Stdout = supervisor.RawLogger(ctx) | 
 | 	cmd.Stderr = supervisor.RawLogger(ctx) | 
 | 	return supervisor.RunCommand(ctx, cmd) | 
 | } |