[client] Get static system info once (#2965)

Get static system info once for Windows, Darwin, and Linux nodes

This should improve startup and peer authentication times
This commit is contained in:
Maycon Santos 2024-12-03 10:22:04 +01:00 committed by GitHub
parent a0bf0bdcc0
commit a4826cfb5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 123 additions and 70 deletions

View File

@ -61,6 +61,14 @@ type Info struct {
Files []File // for posture checks 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 // extractUserAgent extracts Netbird's agent (client) name and version from the outgoing context
func extractUserAgent(ctx context.Context) string { func extractUserAgent(ctx context.Context) string {
md, hasMeta := metadata.FromOutgoingContext(ctx) md, hasMeta := metadata.FromOutgoingContext(ctx)

View File

@ -10,13 +10,12 @@ import (
"os/exec" "os/exec"
"runtime" "runtime"
"strings" "strings"
"time"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
log "github.com/sirupsen/logrus" 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" "github.com/netbirdio/netbird/version"
) )
@ -41,11 +40,10 @@ func GetInfo(ctx context.Context) *Info {
log.Warnf("failed to discover network addresses: %s", err) log.Warnf("failed to discover network addresses: %s", err)
} }
serialNum, prodName, manufacturer := sysInfo() start := time.Now()
si := updateStaticInfo()
env := Environment{ if time.Since(start) > 1*time.Second {
Cloud: detect_cloud.Detect(ctx), log.Warnf("updateStaticInfo took %s", time.Since(start))
Platform: detect_platform.Detect(ctx),
} }
gio := &Info{ gio := &Info{
@ -57,10 +55,10 @@ func GetInfo(ctx context.Context) *Info {
CPUs: runtime.NumCPU(), CPUs: runtime.NumCPU(),
KernelVersion: release, KernelVersion: release,
NetworkAddresses: addrs, NetworkAddresses: addrs,
SystemSerialNumber: serialNum, SystemSerialNumber: si.SystemSerialNumber,
SystemProductName: prodName, SystemProductName: si.SystemProductName,
SystemManufacturer: manufacturer, SystemManufacturer: si.SystemManufacturer,
Environment: env, Environment: si.Environment,
} }
systemHostname, _ := os.Hostname() systemHostname, _ := os.Hostname()

View File

@ -1,5 +1,4 @@
//go:build !android //go:build !android
// +build !android
package system package system
@ -16,30 +15,13 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/zcalusic/sysinfo" "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" "github.com/netbirdio/netbird/version"
) )
type SysInfoGetter interface { var (
GetSysInfo() SysInfo // it is override in tests
} getSystemInfo = defaultSysInfoImplementation
)
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,
}
}
// GetInfo retrieves and parses the system information // GetInfo retrieves and parses the system information
func GetInfo(ctx context.Context) *Info { func GetInfo(ctx context.Context) *Info {
@ -65,12 +47,10 @@ func GetInfo(ctx context.Context) *Info {
log.Warnf("failed to discover network addresses: %s", err) log.Warnf("failed to discover network addresses: %s", err)
} }
si := SysInfoWrapper{} start := time.Now()
serialNum, prodName, manufacturer := sysInfo(si.GetSysInfo()) si := updateStaticInfo()
if time.Since(start) > 1*time.Second {
env := Environment{ log.Warnf("updateStaticInfo took %s", time.Since(start))
Cloud: detect_cloud.Detect(ctx),
Platform: detect_platform.Detect(ctx),
} }
gio := &Info{ gio := &Info{
@ -85,10 +65,10 @@ func GetInfo(ctx context.Context) *Info {
UIVersion: extractUserAgent(ctx), UIVersion: extractUserAgent(ctx),
KernelVersion: osInfo[1], KernelVersion: osInfo[1],
NetworkAddresses: addrs, NetworkAddresses: addrs,
SystemSerialNumber: serialNum, SystemSerialNumber: si.SystemSerialNumber,
SystemProductName: prodName, SystemProductName: si.SystemProductName,
SystemManufacturer: manufacturer, SystemManufacturer: si.SystemManufacturer,
Environment: env, Environment: si.Environment,
} }
return gio return gio
@ -108,9 +88,9 @@ func _getInfo() string {
return out.String() return out.String()
} }
func sysInfo(si SysInfo) (string, string, string) { func sysInfo() (string, string, string) {
isascii := regexp.MustCompile("^[[:ascii:]]+$") isascii := regexp.MustCompile("^[[:ascii:]]+$")
si := getSystemInfo()
serials := []string{si.ChassisSerial, si.ProductSerial} serials := []string{si.ChassisSerial, si.ProductSerial}
serial := "" serial := ""
@ -141,3 +121,16 @@ func sysInfo(si SysInfo) (string, string, string) {
} }
return serial, name, manufacturer 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,
}
}

View File

@ -6,13 +6,12 @@ import (
"os" "os"
"runtime" "runtime"
"strings" "strings"
"time"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/yusufpapurcu/wmi" "github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows/registry" "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" "github.com/netbirdio/netbird/version"
) )
@ -42,24 +41,10 @@ func GetInfo(ctx context.Context) *Info {
log.Warnf("failed to discover network addresses: %s", err) log.Warnf("failed to discover network addresses: %s", err)
} }
serialNum, err := sysNumber() start := time.Now()
if err != nil { si := updateStaticInfo()
log.Warnf("failed to get system serial number: %s", err) if time.Since(start) > 1*time.Second {
} log.Warnf("updateStaticInfo took %s", time.Since(start))
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),
} }
gio := &Info{ gio := &Info{
@ -71,10 +56,10 @@ func GetInfo(ctx context.Context) *Info {
CPUs: runtime.NumCPU(), CPUs: runtime.NumCPU(),
KernelVersion: buildVersion, KernelVersion: buildVersion,
NetworkAddresses: addrs, NetworkAddresses: addrs,
SystemSerialNumber: serialNum, SystemSerialNumber: si.SystemSerialNumber,
SystemProductName: prodName, SystemProductName: si.SystemProductName,
SystemManufacturer: manufacturer, SystemManufacturer: si.SystemManufacturer,
Environment: env, Environment: si.Environment,
} }
systemHostname, _ := os.Hostname() systemHostname, _ := os.Hostname()
@ -85,6 +70,26 @@ func GetInfo(ctx context.Context) *Info {
return gio 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) { func getOSNameAndVersion() (string, string) {
var dst []Win32_OperatingSystem var dst []Win32_OperatingSystem
query := wmi.CreateQuery(&dst, "") query := wmi.CreateQuery(&dst, "")

View File

@ -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
}

View File

@ -183,7 +183,10 @@ func Test_sysInfo(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { 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 { if gotSerialNum != tt.wantSerialNum {
t.Errorf("sysInfo() gotSerialNum = %v, want %v", gotSerialNum, tt.wantSerialNum) t.Errorf("sysInfo() gotSerialNum = %v, want %v", gotSerialNum, tt.wantSerialNum)
} }