Skip to content

Commit

Permalink
[client] Get static system info once (#2965)
Browse files Browse the repository at this point in the history
Get static system info once for Windows, Darwin, and Linux nodes

This should improve startup and peer authentication times
  • Loading branch information
mlsmaycon authored Dec 3, 2024
1 parent a0bf0bd commit a4826cf
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 70 deletions.
8 changes: 8 additions & 0 deletions client/system/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ type Info struct {
Files []File // for posture checks
}

// StaticInfo is an object that contains machine information that does not change
type StaticInfo struct {
SystemSerialNumber string
SystemProductName string
SystemManufacturer string
Environment Environment
}

// extractUserAgent extracts Netbird's agent (client) name and version from the outgoing context
func extractUserAgent(ctx context.Context) string {
md, hasMeta := metadata.FromOutgoingContext(ctx)
Expand Down
20 changes: 9 additions & 11 deletions client/system/info_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import (
"os/exec"
"runtime"
"strings"
"time"

"golang.org/x/sys/unix"

log "github.com/sirupsen/logrus"

"github.com/netbirdio/netbird/client/system/detect_cloud"
"github.com/netbirdio/netbird/client/system/detect_platform"
"github.com/netbirdio/netbird/version"
)

Expand All @@ -41,11 +40,10 @@ func GetInfo(ctx context.Context) *Info {
log.Warnf("failed to discover network addresses: %s", err)
}

serialNum, prodName, manufacturer := sysInfo()

env := Environment{
Cloud: detect_cloud.Detect(ctx),
Platform: detect_platform.Detect(ctx),
start := time.Now()
si := updateStaticInfo()
if time.Since(start) > 1*time.Second {
log.Warnf("updateStaticInfo took %s", time.Since(start))
}

gio := &Info{
Expand All @@ -57,10 +55,10 @@ func GetInfo(ctx context.Context) *Info {
CPUs: runtime.NumCPU(),
KernelVersion: release,
NetworkAddresses: addrs,
SystemSerialNumber: serialNum,
SystemProductName: prodName,
SystemManufacturer: manufacturer,
Environment: env,
SystemSerialNumber: si.SystemSerialNumber,
SystemProductName: si.SystemProductName,
SystemManufacturer: si.SystemManufacturer,
Environment: si.Environment,
}

systemHostname, _ := os.Hostname()
Expand Down
61 changes: 27 additions & 34 deletions client/system/info_linux.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build !android
// +build !android

package system

Expand All @@ -16,30 +15,13 @@ import (
log "github.com/sirupsen/logrus"
"github.com/zcalusic/sysinfo"

"github.com/netbirdio/netbird/client/system/detect_cloud"
"github.com/netbirdio/netbird/client/system/detect_platform"
"github.com/netbirdio/netbird/version"
)

type SysInfoGetter interface {
GetSysInfo() SysInfo
}

type SysInfoWrapper struct {
si sysinfo.SysInfo
}

func (s SysInfoWrapper) GetSysInfo() SysInfo {
s.si.GetSysInfo()
return SysInfo{
ChassisSerial: s.si.Chassis.Serial,
ProductSerial: s.si.Product.Serial,
BoardSerial: s.si.Board.Serial,
ProductName: s.si.Product.Name,
BoardName: s.si.Board.Name,
ProductVendor: s.si.Product.Vendor,
}
}
var (
// it is override in tests
getSystemInfo = defaultSysInfoImplementation
)

// GetInfo retrieves and parses the system information
func GetInfo(ctx context.Context) *Info {
Expand All @@ -65,12 +47,10 @@ func GetInfo(ctx context.Context) *Info {
log.Warnf("failed to discover network addresses: %s", err)
}

si := SysInfoWrapper{}
serialNum, prodName, manufacturer := sysInfo(si.GetSysInfo())

env := Environment{
Cloud: detect_cloud.Detect(ctx),
Platform: detect_platform.Detect(ctx),
start := time.Now()
si := updateStaticInfo()
if time.Since(start) > 1*time.Second {
log.Warnf("updateStaticInfo took %s", time.Since(start))
}

gio := &Info{
Expand All @@ -85,10 +65,10 @@ func GetInfo(ctx context.Context) *Info {
UIVersion: extractUserAgent(ctx),
KernelVersion: osInfo[1],
NetworkAddresses: addrs,
SystemSerialNumber: serialNum,
SystemProductName: prodName,
SystemManufacturer: manufacturer,
Environment: env,
SystemSerialNumber: si.SystemSerialNumber,
SystemProductName: si.SystemProductName,
SystemManufacturer: si.SystemManufacturer,
Environment: si.Environment,
}

return gio
Expand All @@ -108,9 +88,9 @@ func _getInfo() string {
return out.String()
}

func sysInfo(si SysInfo) (string, string, string) {
func sysInfo() (string, string, string) {
isascii := regexp.MustCompile("^[[:ascii:]]+$")

si := getSystemInfo()
serials := []string{si.ChassisSerial, si.ProductSerial}
serial := ""

Expand Down Expand Up @@ -141,3 +121,16 @@ func sysInfo(si SysInfo) (string, string, string) {
}
return serial, name, manufacturer
}

func defaultSysInfoImplementation() SysInfo {
si := sysinfo.SysInfo{}
si.GetSysInfo()
return SysInfo{
ChassisSerial: si.Chassis.Serial,
ProductSerial: si.Product.Serial,
BoardSerial: si.Board.Serial,
ProductName: si.Product.Name,
BoardName: si.Board.Name,
ProductVendor: si.Product.Vendor,
}
}
53 changes: 29 additions & 24 deletions client/system/info_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ import (
"os"
"runtime"
"strings"
"time"

log "github.com/sirupsen/logrus"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows/registry"

"github.com/netbirdio/netbird/client/system/detect_cloud"
"github.com/netbirdio/netbird/client/system/detect_platform"
"github.com/netbirdio/netbird/version"
)

Expand Down Expand Up @@ -42,24 +41,10 @@ func GetInfo(ctx context.Context) *Info {
log.Warnf("failed to discover network addresses: %s", err)
}

serialNum, err := sysNumber()
if err != nil {
log.Warnf("failed to get system serial number: %s", err)
}

prodName, err := sysProductName()
if err != nil {
log.Warnf("failed to get system product name: %s", err)
}

manufacturer, err := sysManufacturer()
if err != nil {
log.Warnf("failed to get system manufacturer: %s", err)
}

env := Environment{
Cloud: detect_cloud.Detect(ctx),
Platform: detect_platform.Detect(ctx),
start := time.Now()
si := updateStaticInfo()
if time.Since(start) > 1*time.Second {
log.Warnf("updateStaticInfo took %s", time.Since(start))
}

gio := &Info{
Expand All @@ -71,10 +56,10 @@ func GetInfo(ctx context.Context) *Info {
CPUs: runtime.NumCPU(),
KernelVersion: buildVersion,
NetworkAddresses: addrs,
SystemSerialNumber: serialNum,
SystemProductName: prodName,
SystemManufacturer: manufacturer,
Environment: env,
SystemSerialNumber: si.SystemSerialNumber,
SystemProductName: si.SystemProductName,
SystemManufacturer: si.SystemManufacturer,
Environment: si.Environment,
}

systemHostname, _ := os.Hostname()
Expand All @@ -85,6 +70,26 @@ func GetInfo(ctx context.Context) *Info {
return gio
}

func sysInfo() (serialNumber string, productName string, manufacturer string) {
var err error
serialNumber, err = sysNumber()
if err != nil {
log.Warnf("failed to get system serial number: %s", err)
}

productName, err = sysProductName()
if err != nil {
log.Warnf("failed to get system product name: %s", err)
}

manufacturer, err = sysManufacturer()
if err != nil {
log.Warnf("failed to get system manufacturer: %s", err)
}

return serialNumber, productName, manufacturer
}

func getOSNameAndVersion() (string, string) {
var dst []Win32_OperatingSystem
query := wmi.CreateQuery(&dst, "")
Expand Down
46 changes: 46 additions & 0 deletions client/system/static_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//go:build (linux && !android) || windows || (darwin && !ios)

package system

import (
"context"
"sync"
"time"

"github.com/netbirdio/netbird/client/system/detect_cloud"
"github.com/netbirdio/netbird/client/system/detect_platform"
)

var (
staticInfo StaticInfo
once sync.Once
)

func init() {
go func() {
_ = updateStaticInfo()
}()
}

func updateStaticInfo() StaticInfo {
once.Do(func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
wg := sync.WaitGroup{}
wg.Add(3)
go func() {
staticInfo.SystemSerialNumber, staticInfo.SystemProductName, staticInfo.SystemManufacturer = sysInfo()
wg.Done()
}()
go func() {
staticInfo.Environment.Cloud = detect_cloud.Detect(ctx)
wg.Done()
}()
go func() {
staticInfo.Environment.Platform = detect_platform.Detect(ctx)
wg.Done()
}()
wg.Wait()
})
return staticInfo
}
5 changes: 4 additions & 1 deletion client/system/sysinfo_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,10 @@ func Test_sysInfo(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotSerialNum, gotProdName, gotManufacturer := sysInfo(tt.sysInfo)
getSystemInfo = func() SysInfo {
return tt.sysInfo
}
gotSerialNum, gotProdName, gotManufacturer := sysInfo()
if gotSerialNum != tt.wantSerialNum {
t.Errorf("sysInfo() gotSerialNum = %v, want %v", gotSerialNum, tt.wantSerialNum)
}
Expand Down

0 comments on commit a4826cf

Please sign in to comment.