feat: add more hardware information to the link status resources
The new fields will be used by the network device selector. Signed-off-by: Artem Chernyshev <artem.chernyshev@talos-systems.com>
This commit is contained in:
parent
2ff6db749a
commit
5d52802001
@ -213,6 +213,19 @@ func (ctrl *LinkStatusController) reconcile(ctx context.Context, r controller.Ru
|
||||
status.Duplex = nethelpers.Duplex(ethtool.Unknown)
|
||||
}
|
||||
|
||||
var deviceInfo *nethelpers.DeviceInfo
|
||||
|
||||
deviceInfo, err = nethelpers.GetDeviceInfo(link.Attributes.Name)
|
||||
if err != nil {
|
||||
logger.Warn("failure getting device information from /sys/class/net/*", zap.Error(err), zap.String("link", link.Attributes.Name))
|
||||
}
|
||||
|
||||
if deviceInfo != nil {
|
||||
status.BusPath = deviceInfo.BusPath
|
||||
status.Driver = deviceInfo.Driver
|
||||
status.PCIID = deviceInfo.PCIID
|
||||
}
|
||||
|
||||
switch status.Kind {
|
||||
case network.LinkKindVLAN:
|
||||
if err = networkadapter.VLANSpec(&status.VLAN).Decode(link.Attributes.Info.Data); err != nil {
|
||||
|
@ -7,10 +7,12 @@ package network_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@ -125,6 +127,59 @@ func (suite *LinkStatusSuite) assertNoInterface(id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (suite *LinkStatusSuite) TestInterfaceHwInfo() {
|
||||
errNoInterfaces := fmt.Errorf("no suitable interfaces found")
|
||||
|
||||
err := retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
for _, res := range resources.Items {
|
||||
spec := res.(*network.LinkStatus).TypedSpec() //nolint:errcheck,forcetypeassert
|
||||
|
||||
if !spec.Physical() {
|
||||
continue
|
||||
}
|
||||
|
||||
if spec.Type != nethelpers.LinkEther {
|
||||
continue
|
||||
}
|
||||
|
||||
emptyFields := []string{}
|
||||
|
||||
for key, value := range map[string]string{
|
||||
"hw addr": spec.HardwareAddr.String(),
|
||||
"driver": spec.Driver,
|
||||
"bus path": spec.BusPath,
|
||||
"PCI id": spec.PCIID,
|
||||
} {
|
||||
if value == "" {
|
||||
emptyFields = append(emptyFields, key)
|
||||
}
|
||||
}
|
||||
|
||||
if len(emptyFields) > 0 {
|
||||
return fmt.Errorf("the interface %s has the following fields empty: %s", res.Metadata().ID(), strings.Join(emptyFields, ", "))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return retry.ExpectedError(errNoInterfaces)
|
||||
},
|
||||
)
|
||||
|
||||
if errors.Is(err, errNoInterfaces) {
|
||||
suite.T().Skip(err.Error())
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (suite *LinkStatusSuite) TestLoopbackInterface() {
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
|
78
pkg/machinery/nethelpers/device.go
Normal file
78
pkg/machinery/nethelpers/device.go
Normal file
@ -0,0 +1,78 @@
|
||||
// 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 nethelpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DeviceInfo contains device hardware information that can be read from /sys/.
|
||||
type DeviceInfo struct {
|
||||
BusPath string
|
||||
PCIID string
|
||||
Driver string
|
||||
}
|
||||
|
||||
// GetDeviceInfo get additional device information by reading /sys/ directory.
|
||||
//nolint:gocyclo
|
||||
func GetDeviceInfo(deviceName string) (*DeviceInfo, error) {
|
||||
path := filepath.Join("/sys/class/net/", deviceName, "/device/")
|
||||
|
||||
readFile := func(path string) (string, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(bytes.TrimSpace(res)), nil
|
||||
}
|
||||
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return &DeviceInfo{}, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ueventContents, err := readFile(filepath.Join(path, "uevent"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ueventContents == "" {
|
||||
return &DeviceInfo{}, nil
|
||||
}
|
||||
|
||||
device := &DeviceInfo{}
|
||||
|
||||
for _, line := range strings.Split(ueventContents, "\n") {
|
||||
key, value, found := strings.Cut(line, "=")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
switch key {
|
||||
case "DRIVER":
|
||||
device.Driver = value
|
||||
case "PCI_ID":
|
||||
device.PCIID = value
|
||||
case "PCI_SLOT_NAME":
|
||||
device.BusPath = value
|
||||
}
|
||||
}
|
||||
|
||||
return device, nil
|
||||
}
|
@ -34,6 +34,9 @@ type LinkStatusSpec struct {
|
||||
OperationalState nethelpers.OperationalState `yaml:"operationalState"`
|
||||
Kind string `yaml:"kind"`
|
||||
SlaveKind string `yaml:"slaveKind"`
|
||||
BusPath string `yaml:"busPath,omitempty"`
|
||||
PCIID string `yaml:"pciID,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty"`
|
||||
// Fields coming from ethtool API.
|
||||
LinkState bool `yaml:"linkState"`
|
||||
SpeedMegabits int `yaml:"speedMbit,omitempty"`
|
||||
|
@ -99,6 +99,37 @@ NODE NAMESPACE TYPE ID VERSION RESOLVERS
|
||||
172.20.0.2 network ResolverStatus resolvers 2 ["8.8.8.8","1.1.1.1"]
|
||||
```
|
||||
|
||||
```sh
|
||||
$ talosctl get links -o yaml
|
||||
node: 172.20.0.2
|
||||
metadata:
|
||||
namespace: network
|
||||
type: LinkStatuses.net.talos.dev
|
||||
id: eth0
|
||||
version: 2
|
||||
owner: network.LinkStatusController
|
||||
phase: running
|
||||
created: 2021-06-29T20:23:18Z
|
||||
updated: 2021-06-29T20:23:18Z
|
||||
spec:
|
||||
index: 4
|
||||
type: ether
|
||||
linkIndex: 0
|
||||
flags: UP,BROADCAST,RUNNING,MULTICAST,LOWER_UP
|
||||
hardwareAddr: 4e:95:8e:8f:e4:47
|
||||
broadcastAddr: ff:ff:ff:ff:ff:ff
|
||||
mtu: 1500
|
||||
queueDisc: pfifo_fast
|
||||
operationalState: up
|
||||
kind: ""
|
||||
slaveKind: ""
|
||||
driver: virtio_net
|
||||
linkState: true
|
||||
speedMbit: 4294967295
|
||||
port: Other
|
||||
duplex: Unknown
|
||||
```
|
||||
|
||||
## Inspecting Configuration
|
||||
|
||||
The desired networking configuration is combined from multiple sources and presented
|
||||
|
Loading…
x
Reference in New Issue
Block a user