feature/sdnotify: move util/systemd to a modular feature
Updates #12614 Change-Id: I08e714c83b455df7f538cc99cafe940db936b480 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
7bcab4ab28
commit
976389c0f7
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Code generated by gen.go; DO NOT EDIT.
|
||||
|
||||
//go:build ts_omit_sdnotify
|
||||
|
||||
package buildfeatures
|
||||
|
||||
// HasSDNotify is whether the binary was built with support for modular feature "systemd notification support".
|
||||
// Specifically, it's whether the binary was NOT built with the "ts_omit_sdnotify" build tag.
|
||||
// It's a const so it can be used for dead code elimination.
|
||||
const HasSDNotify = false
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Code generated by gen.go; DO NOT EDIT.
|
||||
|
||||
//go:build !ts_omit_sdnotify
|
||||
|
||||
package buildfeatures
|
||||
|
||||
// HasSDNotify is whether the binary was built with support for modular feature "systemd notification support".
|
||||
// Specifically, it's whether the binary was NOT built with the "ts_omit_sdnotify" build tag.
|
||||
// It's a const so it can be used for dead code elimination.
|
||||
const HasSDNotify = true
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build linux && !ts_omit_sdnotify
|
||||
|
||||
package condregister
|
||||
|
||||
import _ "tailscale.com/feature/sdnotify"
|
||||
@@ -145,6 +145,10 @@ var Features = map[FeatureTag]FeatureMeta{
|
||||
Desc: "Linux systemd-resolved integration",
|
||||
Deps: []FeatureTag{"dbus"},
|
||||
},
|
||||
"sdnotify": {
|
||||
Sym: "SDNotify",
|
||||
Desc: "systemd notification support",
|
||||
},
|
||||
"serve": {
|
||||
Sym: "Serve",
|
||||
Desc: "Serve and Funnel support",
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package feature
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
)
|
||||
|
||||
// HookSystemdReady sends a readiness to systemd. This will unblock service
|
||||
// dependents from starting.
|
||||
var HookSystemdReady Hook[func()]
|
||||
|
||||
// HookSystemdStatus holds a func that will send a single line status update to
|
||||
// systemd so that information shows up in systemctl output.
|
||||
var HookSystemdStatus Hook[func(format string, args ...any)]
|
||||
|
||||
// SystemdStatus sends a single line status update to systemd so that
|
||||
// information shows up in systemctl output.
|
||||
//
|
||||
// It does nothing on non-Linux systems or if the binary was built without
|
||||
// the sdnotify feature.
|
||||
func SystemdStatus(format string, args ...any) {
|
||||
if runtime.GOOS != "linux" || !buildfeatures.HasSDNotify {
|
||||
return
|
||||
}
|
||||
if f, ok := HookSystemdStatus.GetOk(); ok {
|
||||
f(format, args...)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
/*
|
||||
Package sdnotify contains a minimal wrapper around systemd-notify to enable
|
||||
applications to signal readiness and status to systemd.
|
||||
|
||||
This package will only have effect on Linux systems running Tailscale in a
|
||||
systemd unit with the Type=notify flag set. On other operating systems (or
|
||||
when running in a Linux distro without being run from inside systemd) this
|
||||
package will become a no-op.
|
||||
*/
|
||||
package sdnotify
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build linux && !android
|
||||
|
||||
package sdnotify
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/mdlayher/sdnotify"
|
||||
"tailscale.com/feature"
|
||||
)
|
||||
|
||||
func init() {
|
||||
feature.HookSystemdReady.Set(ready)
|
||||
feature.HookSystemdStatus.Set(status)
|
||||
}
|
||||
|
||||
var getNotifyOnce struct {
|
||||
sync.Once
|
||||
v *sdnotify.Notifier
|
||||
}
|
||||
|
||||
type logOnce struct {
|
||||
sync.Once
|
||||
}
|
||||
|
||||
func (l *logOnce) logf(format string, args ...any) {
|
||||
l.Once.Do(func() {
|
||||
log.Printf(format, args...)
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
readyOnce = &logOnce{}
|
||||
statusOnce = &logOnce{}
|
||||
)
|
||||
|
||||
func notifier() *sdnotify.Notifier {
|
||||
getNotifyOnce.Do(func() {
|
||||
var err error
|
||||
getNotifyOnce.v, err = sdnotify.New()
|
||||
// Not exist means probably not running under systemd, so don't log.
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
log.Printf("systemd: systemd-notifier error: %v", err)
|
||||
}
|
||||
})
|
||||
return getNotifyOnce.v
|
||||
}
|
||||
|
||||
// ready signals readiness to systemd. This will unblock service dependents from starting.
|
||||
func ready() {
|
||||
err := notifier().Notify(sdnotify.Ready)
|
||||
if err != nil {
|
||||
readyOnce.logf("systemd: error notifying: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// status sends a single line status update to systemd so that information shows up
|
||||
// in systemctl output. For example:
|
||||
//
|
||||
// $ systemctl status tailscale
|
||||
// ● tailscale.service - Tailscale client daemon
|
||||
// Loaded: loaded (/nix/store/qc312qcy907wz80fqrgbbm8a9djafmlg-unit-tailscale.service/tailscale.service; enabled; vendor preset: enabled)
|
||||
// Active: active (running) since Tue 2020-11-24 17:54:07 EST; 13h ago
|
||||
// Main PID: 26741 (.tailscaled-wra)
|
||||
// Status: "Connected; user@host.domain.tld; 100.101.102.103"
|
||||
// IP: 0B in, 0B out
|
||||
// Tasks: 22 (limit: 4915)
|
||||
// Memory: 30.9M
|
||||
// CPU: 2min 38.469s
|
||||
// CGroup: /system.slice/tailscale.service
|
||||
// └─26741 /nix/store/sv6cj4mw2jajm9xkbwj07k29dj30lh0n-tailscale-date.20200727/bin/tailscaled --port 41641
|
||||
func status(format string, args ...any) {
|
||||
err := notifier().Notify(sdnotify.Statusf(format, args...))
|
||||
if err != nil {
|
||||
statusOnce.logf("systemd: error notifying: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user