fix(inputs.chrony): Use DGRAM for the unix socket (#15552)
This commit is contained in:
parent
72ca42b743
commit
9df480039a
|
|
@ -40,8 +40,23 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||||
## sources -- extended information about peers
|
## sources -- extended information about peers
|
||||||
## sourcestats -- statistics on peers
|
## sourcestats -- statistics on peers
|
||||||
# metrics = ["tracking"]
|
# metrics = ["tracking"]
|
||||||
|
|
||||||
|
## Socket group & permissions
|
||||||
|
## If the user requests collecting metrics via unix socket, then it is created
|
||||||
|
## with the following group and permissions.
|
||||||
|
# socket_group = "chrony"
|
||||||
|
# socket_perms = "0660"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Local socket permissions
|
||||||
|
|
||||||
|
To use the unix socket, telegraf must be able to talk to it. Please ensure that
|
||||||
|
the telegraf user is a member of the `chrony` group or telegraf won't be able to
|
||||||
|
use the socket!
|
||||||
|
|
||||||
|
The unix socket is needed in order to use the `serverstats` metrics. All other
|
||||||
|
metrics can be gathered using the udp connection.
|
||||||
|
|
||||||
## Metrics
|
## Metrics
|
||||||
|
|
||||||
- chrony
|
- chrony
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,15 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
fbchrony "github.com/facebook/time/ntp/chrony"
|
fbchrony "github.com/facebook/time/ntp/chrony"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
"github.com/influxdata/telegraf/config"
|
"github.com/influxdata/telegraf/config"
|
||||||
|
|
@ -24,21 +28,61 @@ import (
|
||||||
var sampleConfig string
|
var sampleConfig string
|
||||||
|
|
||||||
type Chrony struct {
|
type Chrony struct {
|
||||||
Server string `toml:"server"`
|
Server string `toml:"server"`
|
||||||
Timeout config.Duration `toml:"timeout"`
|
Timeout config.Duration `toml:"timeout"`
|
||||||
DNSLookup bool `toml:"dns_lookup"`
|
DNSLookup bool `toml:"dns_lookup"`
|
||||||
Metrics []string `toml:"metrics"`
|
SocketGroup string `toml:"socket_group"`
|
||||||
Log telegraf.Logger `toml:"-"`
|
SocketPerms string `toml:"socket_perms"`
|
||||||
|
Metrics []string `toml:"metrics"`
|
||||||
|
Log telegraf.Logger `toml:"-"`
|
||||||
|
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
client *fbchrony.Client
|
client *fbchrony.Client
|
||||||
source string
|
source string
|
||||||
|
local string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Chrony) SampleConfig() string {
|
func (*Chrony) SampleConfig() string {
|
||||||
return sampleConfig
|
return sampleConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dialUnix opens an unixgram connection with chrony
|
||||||
|
func (c *Chrony) dialUnix(address string) (*net.UnixConn, error) {
|
||||||
|
dir := path.Dir(address)
|
||||||
|
c.local = path.Join(dir, fmt.Sprintf("chrony-telegraf-%s.sock", uuid.New().String()))
|
||||||
|
conn, err := net.DialUnix("unixgram",
|
||||||
|
&net.UnixAddr{Name: c.local, Net: "unixgram"},
|
||||||
|
&net.UnixAddr{Name: address, Net: "unixgram"},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
filemode, err := strconv.ParseUint(c.SocketPerms, 8, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing file mode %q failed: %w", c.SocketPerms, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Chmod(c.local, os.FileMode(filemode)); err != nil {
|
||||||
|
return nil, fmt.Errorf("changing file mode of %q failed: %w", c.local, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
group, err := user.LookupGroup(c.SocketGroup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("looking up group %q failed: %w", c.SocketGroup, err)
|
||||||
|
}
|
||||||
|
gid, err := strconv.Atoi(group.Gid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing group ID %q failed: %w", group.Gid, err)
|
||||||
|
}
|
||||||
|
if err := os.Chown(c.local, os.Getuid(), gid); err != nil {
|
||||||
|
return nil, fmt.Errorf("changing group of %q failed: %w", c.local, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Chrony) Init() error {
|
func (c *Chrony) Init() error {
|
||||||
// Use the configured server, if none set, we try to guess it in Start()
|
// Use the configured server, if none set, we try to guess it in Start()
|
||||||
if c.Server != "" {
|
if c.Server != "" {
|
||||||
|
|
@ -48,7 +92,7 @@ func (c *Chrony) Init() error {
|
||||||
return fmt.Errorf("parsing server address failed: %w", err)
|
return fmt.Errorf("parsing server address failed: %w", err)
|
||||||
}
|
}
|
||||||
switch u.Scheme {
|
switch u.Scheme {
|
||||||
case "unix":
|
case "unixgram":
|
||||||
// Keep the server unmodified
|
// Keep the server unmodified
|
||||||
case "udp":
|
case "udp":
|
||||||
// Check if we do have a port and add the default port if we don't
|
// Check if we do have a port and add the default port if we don't
|
||||||
|
|
@ -79,6 +123,14 @@ func (c *Chrony) Init() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.SocketGroup == "" {
|
||||||
|
c.SocketGroup = "chrony"
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.SocketPerms == "" {
|
||||||
|
c.SocketPerms = "0660"
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,8 +142,8 @@ func (c *Chrony) Start(_ telegraf.Accumulator) error {
|
||||||
return fmt.Errorf("parsing server address failed: %w", err)
|
return fmt.Errorf("parsing server address failed: %w", err)
|
||||||
}
|
}
|
||||||
switch u.Scheme {
|
switch u.Scheme {
|
||||||
case "unix":
|
case "unixgram":
|
||||||
conn, err := net.DialTimeout("unix", u.Path, time.Duration(c.Timeout))
|
conn, err := c.dialUnix(u.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("dialing %q failed: %w", c.Server, err)
|
return fmt.Errorf("dialing %q failed: %w", c.Server, err)
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +159,7 @@ func (c *Chrony) Start(_ telegraf.Accumulator) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If no server is given, reproduce chronyc's behavior
|
// If no server is given, reproduce chronyc's behavior
|
||||||
if conn, err := net.DialTimeout("unix", "/run/chrony/chronyd.sock", time.Duration(c.Timeout)); err == nil {
|
if conn, err := c.dialUnix("/run/chrony/chronyd.sock"); err == nil {
|
||||||
c.Server = "unix:///run/chrony/chronyd.sock"
|
c.Server = "unix:///run/chrony/chronyd.sock"
|
||||||
c.conn = conn
|
c.conn = conn
|
||||||
} else if conn, err := net.DialTimeout("udp", "127.0.0.1:323", time.Duration(c.Timeout)); err == nil {
|
} else if conn, err := net.DialTimeout("udp", "127.0.0.1:323", time.Duration(c.Timeout)); err == nil {
|
||||||
|
|
@ -136,6 +188,11 @@ func (c *Chrony) Stop() {
|
||||||
c.Log.Errorf("Closing connection to %q failed: %v", c.Server, err)
|
c.Log.Errorf("Closing connection to %q failed: %v", c.Server, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if c.local != "" {
|
||||||
|
if err := os.Remove(c.local); err != nil {
|
||||||
|
c.Log.Errorf("Removing temporary socket %q failed: %v", c.local, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chrony) Gather(acc telegraf.Accumulator) error {
|
func (c *Chrony) Gather(acc telegraf.Accumulator) error {
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,9 @@
|
||||||
## sources -- extended information about peers
|
## sources -- extended information about peers
|
||||||
## sourcestats -- statistics on peers
|
## sourcestats -- statistics on peers
|
||||||
# metrics = ["tracking"]
|
# metrics = ["tracking"]
|
||||||
|
|
||||||
|
## Socket group & permissions
|
||||||
|
## If the user requests collecting metrics via unix socket, then it is created
|
||||||
|
## with the following group and permissions.
|
||||||
|
# socket_group = "chrony"
|
||||||
|
# socket_perms = "0660"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue