From c2c789350901a4ef2f65f1e51e7d39d287662791 Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Tue, 12 Mar 2019 21:29:10 +0100 Subject: [PATCH 01/11] fix logic error + little refactor Fix: get cptime of n-th cpu when `percpu` instead of the average. While there, rearrange the last if statement to make the code a bit more homogeneous. --- cpu/cpu_openbsd.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index 0177626..9ede291 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -85,9 +85,9 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { var cpuTimes = make([]int64, CPUStates) var mib []int32 if percpu { - mib = []int32{CTLKern, KernCptime} - } else { mib = []int32{CTLKern, KernCptime2, int32(i)} + } else { + mib = []int32{CTLKern, KernCptime} } buf, _, err := common.CallSyscall(mib) if err != nil { @@ -106,10 +106,10 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec, Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec, } - if !percpu { - c.CPU = "cpu-total" - } else { + if percpu { c.CPU = fmt.Sprintf("cpu%d", i) + } else { + c.CPU = "cpu-total" } ret = append(ret, c) } From 12d92847cfd6a4bd572925239fdfa7d290e2d54d Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Wed, 13 Mar 2019 11:03:17 +0100 Subject: [PATCH 02/11] Get hw.ncpuonline without unix.SysctlUint32 unix.Sysctl always return an error when asking for hw.ncpuonline, so revert to a direct unix.Syscall6 to get the cpu count. --- cpu/cpu_openbsd.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index 9ede291..d224a1b 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -28,6 +28,8 @@ var ( // sys/sysctl.h const ( CTLKern = 1 // "high kernel": proc, limits + CTLHw = 6 // CTL_HW + NCpuOnline = 25 // HW_NCPUONLINE KernCptime = 40 // KERN_CPTIME KernCptime2 = 71 // KERN_CPTIME2 ) @@ -134,10 +136,19 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) { } c.Mhz = float64(u32) - if u32, err = unix.SysctlUint32("hw.ncpuonline"); err != nil { + mib := []int32{CTLHw, NCpuOnline} + buf, _, err := common.CallSyscall(mib) + if err != nil { return nil, err } - c.Cores = int32(u32) + + var ncpu int32 + br := bytes.NewReader(buf) + err = binary.Read(br, binary.LittleEndian, &ncpu) + if err != nil { + return nil, err + } + c.Cores = ncpu if c.ModelName, err = unix.Sysctl("hw.model"); err != nil { return nil, err From 932f2f6049e0fbf62f15f15c3b37d84c900d1d25 Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Sat, 16 Mar 2019 12:26:03 +0100 Subject: [PATCH 03/11] Fix cpu stats when hw.smt is enabled When hw.smt is enabled, and it's enabled by default from 6.4, the number of cpus given by `runtime.NumCPU()` is half of the total: only the cpuN with N = 0,2,4,... are used by the system. We need to detect that and ask for the correct stats. --- cpu/cpu_openbsd.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index d224a1b..54f6ec2 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -29,6 +29,7 @@ var ( const ( CTLKern = 1 // "high kernel": proc, limits CTLHw = 6 // CTL_HW + SMT = 24 // HW_SMT NCpuOnline = 25 // HW_NCPUONLINE KernCptime = 40 // KERN_CPTIME KernCptime2 = 71 // KERN_CPTIME2 @@ -69,6 +70,22 @@ func init() { }() } +func smt() (bool, error) { + mib := []int32{CTLHw, SMT} + buf, _, err := common.CallSyscall(mib) + if err != nil { + return false, err + } + + var ret bool + br := bytes.NewReader(buf) + if err := binary.Read(br, binary.LittleEndian, ret); err != nil { + return false, err + } + + return ret, nil +} + func Times(percpu bool) ([]TimesStat, error) { return TimesWithContext(context.Background(), percpu) } @@ -83,11 +100,21 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { ncpu = 1 } + smt, err := smt() + if err != nil { + return nil, err + } + for i := 0; i < ncpu; i++ { + j := i + if !smt { + j *= 2 + } + var cpuTimes = make([]int64, CPUStates) var mib []int32 if percpu { - mib = []int32{CTLKern, KernCptime2, int32(i)} + mib = []int32{CTLKern, KernCptime2, int32(j)} } else { mib = []int32{CTLKern, KernCptime} } @@ -109,7 +136,7 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec, } if percpu { - c.CPU = fmt.Sprintf("cpu%d", i) + c.CPU = fmt.Sprintf("cpu%d", j) } else { c.CPU = "cpu-total" } From c28fe78291d43b7d61b0dc3b35b968ba55646d03 Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Mon, 18 Mar 2019 19:58:50 +0100 Subject: [PATCH 04/11] forget to take addr --- cpu/cpu_openbsd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index 54f6ec2..04b4e7f 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -79,7 +79,7 @@ func smt() (bool, error) { var ret bool br := bytes.NewReader(buf) - if err := binary.Read(br, binary.LittleEndian, ret); err != nil { + if err := binary.Read(br, binary.LittleEndian, &ret); err != nil { return false, err } From 53ce014b140c06d982700e06d7e9af275bc0820c Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Tue, 19 Mar 2019 20:06:12 +0100 Subject: [PATCH 05/11] handle EOPNOTSUPP when checking for hw.smt if hw.smt is not applicable for the current platform (e.g. i386), pretend it's enabled --- cpu/cpu_openbsd.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index 04b4e7f..52bbcbd 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -10,6 +10,7 @@ import ( "os/exec" "strconv" "strings" + "syscall" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/unix" @@ -101,7 +102,11 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { } smt, err := smt() - if err != nil { + if err == syscall.EOPNOTSUPP { + // if hw.smt is not applicable for this platform (e.g. i386), + // pretend it's enabled + smt = true + } else if err != nil { return nil, err } From 174b31f14621aa208279766cfa575ca9c916f3d7 Mon Sep 17 00:00:00 2001 From: Marc Date: Fri, 26 Apr 2019 23:12:47 +0800 Subject: [PATCH 06/11] Fix for #665 Remains backward compatible. When encountering non-fatal errors SensorsTemperatures() returns the temperatures for all the sensor we could read successfully. In that case the custom error contains a list of all the non-fatal errors encountered. Example usage: _, err := SensorsTemperatures() if err != nil { warns, ok := err.(*Warnings) if ok { fmt.Printf("%v\n", err) for i, w := range warns.List { fmt.Printf("Warning %v: %v\n", i+1, w) } } else { t.Errorf("%v", err) } } --- host/host_linux.go | 10 +++++++--- host/types.go | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 host/types.go diff --git a/host/host_linux.go b/host/host_linux.go index 03b3407..7395db7 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -635,6 +635,7 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err return temperatures, err } } + var warns Warnings // example directory // device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm @@ -660,16 +661,19 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err // Get the name of the temperature you are reading name, err := ioutil.ReadFile(filepath.Join(filepath.Dir(file), "name")) if err != nil { - return temperatures, err + warns.Add(err) + continue } // Get the temperature reading current, err := ioutil.ReadFile(file) if err != nil { - return temperatures, err + warns.Add(err) + continue } temperature, err := strconv.ParseFloat(strings.TrimSpace(string(current)), 64) if err != nil { + warns.Add(err) continue } @@ -679,5 +683,5 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err Temperature: temperature / 1000.0, }) } - return temperatures, nil + return temperatures, warns.Reference() } diff --git a/host/types.go b/host/types.go new file mode 100644 index 0000000..1766e7e --- /dev/null +++ b/host/types.go @@ -0,0 +1,25 @@ +package host + +import ( + "fmt" +) + +type Warnings struct { + List []error +} + +func (w *Warnings) Add(err error) { + w.List = append(w.List, err) +} + +func (w *Warnings) Reference() error { + if len(w.List) > 0 { + return w + } else { + return nil + } +} + +func (w *Warnings) Error() string { + return fmt.Sprintf("Number of warnings: %v", len(w.List)) +} From 3cbb0873de29868bd2ff13ad5f30939d6f749f18 Mon Sep 17 00:00:00 2001 From: Omar Polo Date: Thu, 2 May 2019 12:24:16 +0200 Subject: [PATCH 07/11] int32 is enough -- don't waste space --- cpu/cpu_openbsd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index 52bbcbd..588d1b8 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -116,7 +116,7 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { j *= 2 } - var cpuTimes = make([]int64, CPUStates) + var cpuTimes = make([]int32, CPUStates) var mib []int32 if percpu { mib = []int32{CTLKern, KernCptime2, int32(j)} From 12005ab922c2620a0a92cc15ccdf516f6fc0d650 Mon Sep 17 00:00:00 2001 From: litong Date: Mon, 6 May 2019 07:18:49 +0800 Subject: [PATCH 08/11] use /proc/bus/pci/devices to idenetify a kvm guest --- host/host_linux.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/host/host_linux.go b/host/host_linux.go index 03b3407..857085e 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -566,6 +566,17 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) { } } + filename = common.HostProc("bus/pci/devices") + if common.PathExists(filename) { + contents, err := common.ReadLines(filename) + if err == nil { + if common.StringsContains(contents, "virtio-pci") { + system = "kvm" + role = "guest" + } + } + } + filename = common.HostProc() if common.PathExists(filepath.Join(filename, "bc", "0")) { system = "openvz" From 119f26c1df57a807e12f889c2a595c26dc235619 Mon Sep 17 00:00:00 2001 From: litong Date: Wed, 22 May 2019 11:01:09 +0800 Subject: [PATCH 09/11] use bus/pci/devices to identify a vm guest --- host/host_linux.go | 1 - 1 file changed, 1 deletion(-) diff --git a/host/host_linux.go b/host/host_linux.go index 857085e..ef97c14 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -571,7 +571,6 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) { contents, err := common.ReadLines(filename) if err == nil { if common.StringsContains(contents, "virtio-pci") { - system = "kvm" role = "guest" } } From 2a0b67d19cda8a0a86de2bff4d2d95c8bca02e6a Mon Sep 17 00:00:00 2001 From: Arturo Reuschenbach Puncernau Date: Fri, 24 May 2019 11:33:07 +0200 Subject: [PATCH 10/11] added sles to the suse platform family --- host/host_linux.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/host_linux.go b/host/host_linux.go index 49f52c9..8eab651 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -421,7 +421,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil family = "fedora" case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm": family = "rhel" - case "suse", "opensuse": + case "suse", "opensuse", "sles": family = "suse" case "gentoo": family = "gentoo" From 3af6e1ffe781405a7ff9915ff37754cba707e680 Mon Sep 17 00:00:00 2001 From: Lomanic Date: Fri, 31 May 2019 18:04:45 +0200 Subject: [PATCH 11/11] [host][linux] Properly handle double quotes in /etc/os-release in PlatformInformation --- host/host_linux.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/host_linux.go b/host/host_linux.go index 8eab651..89af40d 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -247,9 +247,9 @@ func getOSRelease() (platform string, version string, err error) { } switch field[0] { case "ID": // use ID for lowercase - platform = field[1] + platform = strings.Trim(field[1], `"`) case "VERSION": - version = field[1] + version = strings.Trim(field[1], `"`) } } return platform, version, nil