Skip to content

Commit

Permalink
Capture network info in health report (#240)
Browse files Browse the repository at this point in the history
Introduce a new struct `NetInfo` to store the driver and firmware
version of a network interface.

Also,

- Introduce a function to populate `NetInfo` for a given interface
- Add `Revision` field for a drive partition and capture it in the
  health diagnostics.
  • Loading branch information
anjalshireesh authored Oct 30, 2023
1 parent cd6ff27 commit f9e74b9
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 16 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/prometheus/client_model v0.4.0
github.com/prometheus/procfs v0.9.0
github.com/prometheus/prom2json v1.3.3
github.com/safchain/ethtool v0.3.0
github.com/secure-io/sio-go v0.3.1
github.com/shirou/gopsutil/v3 v3.23.1
github.com/tinylib/msgp v1.1.8
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ github.com/prometheus/prom2json v1.3.3 h1:IYfSMiZ7sSOfliBoo89PcufjWO4eAR0gznGcET
github.com/prometheus/prom2json v1.3.3/go.mod h1:Pv4yIPktEkK7btWsrUTWDDDrnpUrAELaOCj+oFwlgmc=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4=
Expand Down Expand Up @@ -109,6 +111,7 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
56 changes: 40 additions & 16 deletions health.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2015-2022 MinIO, Inc.
// Copyright (c) 2015-2023 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
Expand Down Expand Up @@ -232,6 +232,7 @@ type Partition struct {

Device string `json:"device,omitempty"`
Model string `json:"model,omitempty"`
Revision string `json:"revision,omitempty"`
Mountpoint string `json:"mountpoint,omitempty"`
FSType string `json:"fs_type,omitempty"`
MountOptions string `json:"mount_options,omitempty"`
Expand All @@ -242,48 +243,69 @@ type Partition struct {
InodeFree uint64 `json:"inode_free,omitempty"`
}

// NetInfo contains information about a network inerface
type NetInfo struct {
NodeCommon
Interface string `json:"interface,omitempty"`
Driver string `json:"driver,omitempty"`
FirmwareVersion string `json:"firmware_version,omitempty"`
}

// Partitions contains all disk partitions information of a node.
type Partitions struct {
NodeCommon

Partitions []Partition `json:"partitions,omitempty"`
}

func getDeviceModel(partDevice string) (string, error) {
var model string
// driveHwInfo contains hardware information about a drive
type driveHwInfo struct {
Model string
Revision string
}

func getDriveHwInfo(partDevice string) (info driveHwInfo, err error) {
partDevName := strings.ReplaceAll(partDevice, devDir, "")
devPath := path.Join(sysClassBlock, partDevName, "dev")

_, err := os.Stat(devPath)
_, err = os.Stat(devPath)
if err != nil {
return model, err
return
}

data, err := ioutil.ReadFile(devPath)
var data []byte
data, err = ioutil.ReadFile(devPath)
if err != nil {
return model, err
return
}

majorMinor := strings.TrimSpace(string(data))
driveInfoPath := runDevDataPfx + majorMinor

f, err := os.Open(driveInfoPath)
var f *os.File
f, err = os.Open(driveInfoPath)
if err != nil {
return model, err
return
}
defer f.Close()

buf := bufio.NewScanner(f)
for buf.Scan() {
field := strings.SplitN(buf.Text(), "=", 2)
if len(field) == 2 && field[0] == "E:ID_MODEL" {
model = field[1]
break
if len(field) == 2 {
if field[0] == "E:ID_MODEL" {
info.Model = field[1]
}
if field[0] == "E:ID_REVISION" {
info.Revision = field[1]
}
if len(info.Model) > 0 && len(info.Revision) > 0 {
break
}
}
}

return model, err
return
}

// GetPartitions returns all disk partitions information of a node running linux only operating system.
Expand Down Expand Up @@ -317,11 +339,11 @@ func GetPartitions(ctx context.Context, addr string) Partitions {
Error: err.Error(),
})
} else {
var model string
var di driveHwInfo
device := parts[i].Device
if strings.HasPrefix(device, devDir) && !strings.HasPrefix(device, devLoopDir) {
// ignore any error in finding device model
model, _ = getDeviceModel(device)
di, _ = getDriveHwInfo(device)
}

partitions = append(partitions, Partition{
Expand All @@ -334,7 +356,8 @@ func GetPartitions(ctx context.Context, addr string) Partitions {
SpaceFree: usage.Free,
InodeTotal: usage.InodesTotal,
InodeFree: usage.InodesFree,
Model: model,
Model: di.Model,
Revision: di.Revision,
})
}
}
Expand Down Expand Up @@ -885,6 +908,7 @@ type SysInfo struct {
OSInfo []OSInfo `json:"osinfo,omitempty"`
MemInfo []MemInfo `json:"meminfo,omitempty"`
ProcInfo []ProcInfo `json:"procinfo,omitempty"`
NetInfo []NetInfo `json:"netinfo,omitempty"`
SysErrs []SysErrors `json:"errors,omitempty"`
SysServices []SysServices `json:"services,omitempty"`
SysConfig []SysConfig `json:"config,omitempty"`
Expand Down
52 changes: 52 additions & 0 deletions net_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//go:build linux
// +build linux

// Copyright (c) 2015-2023 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

package madmin

import (
"fmt"

"github.com/safchain/ethtool"
)

// GetNetInfo returns information of the given network interface
func GetNetInfo(addr string, iface string) (ni NetInfo) {
ni.Addr = addr
ni.Interface = iface

ethHandle, err := ethtool.NewEthtool()
if err != nil {
ni.Error = err.Error()
return
}
defer ethHandle.Close()

di, err := ethHandle.DriverInfo(ni.Interface)
if err != nil {
ni.Error = fmt.Sprintf("Error getting driver info for %s: %s", ni.Interface, err.Error())
return
}

ni.Driver = di.Driver
ni.FirmwareVersion = di.FwVersion

return
}
35 changes: 35 additions & 0 deletions net_nolinux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//go:build !linux
// +build !linux

//
// Copyright (c) 2015-2023 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

package madmin

// GetNetInfo returns information of the given network interface
// Not implemented for non-linux platforms
func GetNetInfo(addr string, iface string) NetInfo {
return NetInfo{
NodeCommon: NodeCommon{
Addr: addr,
Error: "Not implemented for non-linux platforms",
},
Interface: iface,
}
}

0 comments on commit f9e74b9

Please sign in to comment.