Skip to content

Commit

Permalink
Merge pull request #1651 from Dylan-M/aix_support
Browse files Browse the repository at this point in the history
Improve AIX Support
  • Loading branch information
shirou committed May 27, 2024
2 parents 8912445 + 125da53 commit cb52f7a
Show file tree
Hide file tree
Showing 14 changed files with 618 additions and 84 deletions.
110 changes: 56 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ See https://pkg.go.dev/github.com/shirou/gopsutil/v3 or https://godocs.io/github

## Requirements

- go1.16 or above is required.
- go1.18 or above is required.

## More Info

Expand Down Expand Up @@ -184,28 +184,29 @@ Some code is ported from Ohai. Many thanks.

- x: works
- b: almost works, but something is broken

|name |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |Plan 9 |
|----------------------|-------|---------|---------|--------|---------|---------|---------|
|cpu\_times |x |x |x |x |x | |b |
|cpu\_count |x |x |x |x |x | |x |
|cpu\_percent |x |x |x |x |x | | |
|cpu\_times\_percent |x |x |x |x |x | | |
|virtual\_memory |x |x |x |x |x | b |x |
|swap\_memory |x |x |x |x | | |x |
|disk\_partitions |x |x |x |x |x | | |
|disk\_io\_counters |x |x |x | | | | |
|disk\_usage |x |x |x |x |x | | |
|net\_io\_counters |x |x |x |b |x | | |
|boot\_time |x |x |x |x |x | | |
|users |x |x |x |x |x | | |
|pids |x |x |x |x |x | | |
|pid\_exists |x |x |x |x |x | | |
|net\_connections |x |x |x |x | | | |
|net\_protocols |x | | | | | | |
|net\_if\_addrs | | | | | | | |
|net\_if\_stats | | | | | | | |
|netfilter\_conntrack |x | | | | | | |
- c: works in CGO only

|name |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |Plan 9 |AIX |
|----------------------|-------|---------|---------|--------|---------|---------|---------|---------|
|cpu\_times |x |x |x |x |x | |b |x |
|cpu\_count |x |x |x |x |x | |x |x |
|cpu\_percent |x |x |x |x |x | | |x |
|cpu\_times\_percent |x |x |x |x |x | | |x |
|virtual\_memory |x |x |x |x |x | b |x |x |
|swap\_memory |x |x |x |x | | |x |X |
|disk\_partitions |x |x |x |x |x | | |x |
|disk\_io\_counters |x |x |x | | | | | |
|disk\_usage |x |x |x |x |x | | |x |
|net\_io\_counters |x |x |x |b |x | | | |
|boot\_time |x |x |x |x |x | | |X |
|users |x |x |x |x |x | | |x |
|pids |x |x |x |x |x | | | |
|pid\_exists |x |x |x |x |x | | | |
|net\_connections |x |x |x |x | | | |x |
|net\_protocols |x | | | | | | |x |
|net\_if\_addrs | | | | | | | |x |
|net\_if\_stats | | | | | | | |x |
|netfilter\_conntrack |x | | | | | | | |


### Process class
Expand Down Expand Up @@ -254,44 +255,45 @@ Some code is ported from Ohai. Many thanks.

### Original Metrics

|item |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |
|-----------------|-------|---------|---------|--------|--------|---------|
|**HostInfo** | | | | | | |
|hostname |x |x |x |x |x |x |
|uptime |x |x |x |x | |x |
|process |x |x |x | | |x |
|os |x |x |x |x |x |x |
|platform |x |x |x |x | |x |
|platformfamily |x |x |x |x | |x |
|virtualization |x | | | | | |
|**CPU** | | | | | | |
|VendorID |x |x |x |x |x |x |
|Family |x |x |x |x |x |x |
|Model |x |x |x |x |x |x |
|Stepping |x |x |x |x |x |x |
|PhysicalID |x | | | | |x |
|CoreID |x | | | | |x |
|Cores |x | | | |x |x |
|ModelName |x |x |x |x |x |x |
|Microcode |x | | | | |x |
|**LoadAvg** | | | | | | |
|Load1 |x |x |x |x | | |
|Load5 |x |x |x |x | | |
|Load15 |x |x |x |x | | |
|**GetDockerID** | | | | | | |
|container id |x |no |no |no |no | |
|**CgroupsCPU** | | | | | | |
|user |x |no |no |no |no | |
|system |x |no |no |no |no | |
|**CgroupsMem** | | | | | | |
|various |x |no |no |no |no | |
|item |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |AIX |
|-----------------|-------|---------|---------|--------|--------|---------|---------|
|**HostInfo** | | | | | | | |
|hostname |x |x |x |x |x |x |X |
|uptime |x |x |x |x | |x |x |
|process |x |x |x | | |x | |
|os |x |x |x |x |x |x |x |
|platform |x |x |x |x | |x |x |
|platformfamily |x |x |x |x | |x |x |
|virtualization |x | | | | | | |
|**CPU** | | | | | | | |
|VendorID |x |x |x |x |x |x |x |
|Family |x |x |x |x |x |x |x |
|Model |x |x |x |x |x |x |x |
|Stepping |x |x |x |x |x |x | |
|PhysicalID |x | | | | |x | |
|CoreID |x | | | | |x | |
|Cores |x | | | |x |x |x |
|ModelName |x |x |x |x |x |x |x |
|Microcode |x | | | | |x | |
|**LoadAvg** | | | | | | | |
|Load1 |x |x |x |x | | |x |
|Load5 |x |x |x |x | | |x |
|Load15 |x |x |x |x | | |x |
|**GetDockerID** | | | | | | | |
|container id |x |no |no |no |no | | |
|**CgroupsCPU** | | | | | | | |
|user |x |no |no |no |no | | |
|system |x |no |no |no |no | | |
|**CgroupsMem** | | | | | | | |
|various |x |no |no |no |no | | |

- future work
- process_iter
- wait_procs
- Process class
- as_dict
- wait
- AIX processes

## License

Expand Down
79 changes: 72 additions & 7 deletions cpu/cpu_aix_nocgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,57 @@ import (
)

func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
var ret []TimesStat
if percpu {
return []TimesStat{}, common.ErrNotImplementedError
per_out, err := invoke.CommandWithContext(ctx, "sar", "-u", "-P", "ALL", "10", "1")
if err != nil {
return nil, err
}
lines := strings.Split(string(per_out), "\n")
if len(lines) < 6 {
return []TimesStat{}, common.ErrNotImplementedError
}

hp := strings.Fields(lines[5]) // headers
for l := 6; l < len(lines)-1; l++ {
ct := &TimesStat{}
v := strings.Fields(lines[l]) // values
for i, header := range hp {
// We're done in any of these use cases
if i >= len(v) || v[0] == "-" {
break
}

// Position variable for v
pos := i
// There is a missing field at the beginning of all but the first line
// so adjust the position
if l > 6 {
pos = i - 1
}
// We don't want invalid positions
if pos < 0 {
continue
}

if t, err := strconv.ParseFloat(v[pos], 64); err == nil {
switch header {
case `cpu`:
ct.CPU = strconv.FormatFloat(t, 'f', -1, 64)
case `%usr`:
ct.User = t
case `%sys`:
ct.System = t
case `%wio`:
ct.Iowait = t
case `%idle`:
ct.Idle = t
}
}
}
// Valid CPU data, so append it
ret = append(ret, *ct)
}
} else {
out, err := invoke.CommandWithContext(ctx, "sar", "-u", "10", "1")
if err != nil {
Expand All @@ -24,26 +73,28 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
return []TimesStat{}, common.ErrNotImplementedError
}

ret := TimesStat{CPU: "cpu-total"}
ct := &TimesStat{CPU: "cpu-total"}
h := strings.Fields(lines[len(lines)-3]) // headers
v := strings.Fields(lines[len(lines)-2]) // values
for i, header := range h {
if t, err := strconv.ParseFloat(v[i], 64); err == nil {
switch header {
case `%usr`:
ret.User = t
ct.User = t
case `%sys`:
ret.System = t
ct.System = t
case `%wio`:
ret.Iowait = t
ct.Iowait = t
case `%idle`:
ret.Idle = t
ct.Idle = t
}
}
}

return []TimesStat{ret}, nil
ret = append(ret, *ct)
}

return ret, nil
}

func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
Expand Down Expand Up @@ -78,6 +129,20 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
}
}
break
} else if strings.HasPrefix(line, "System Model:") {
p := strings.Split(string(line), ":")
if p != nil {
ret.VendorID = strings.TrimSpace(p[1])
}
} else if strings.HasPrefix(line, "Processor Type:") {
p := strings.Split(string(line), ":")
if p != nil {
c := strings.Split(string(p[1]), "_")
if c != nil {
ret.Family = strings.TrimSpace(c[0])
ret.Model = strings.TrimSpace(c[1])
}
}
}
}
return []InfoStat{ret}, nil
Expand Down
68 changes: 68 additions & 0 deletions cpu/testdata/aix/prtconf
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
System Model: IBM pSeries (emulated by qemu)
Machine Serial Number: Not Available
Processor Type: PowerPC_POWER8
Processor Implementation Mode: POWER 8
Processor Version: PV_8_Compat
Number Of Processors: 4
Processor Clock Speed: 1000 MHz
CPU Type: 64-bit
Kernel Type: 64-bit
LPAR Info: 0 aix_7200-04-02-2027
Memory Size: 4096 MB
Good Memory Size: 4096 MB
Platform Firmware level: Not Available
Firmware Version: SLOF,HEAD
Console Login: enable
Auto Restart: true
Full Core: false
NX Crypto Acceleration: Not Capable
In-Core Crypto Acceleration: Capable, but not Enabled

en0
Network Information
Host Name: aix72-dylan
IP Address: 192.168.124.53
Sub Netmask:
Gateway: 192.168.124.1
Name Server:
Domain Name:

Paging Space Information
Total Paging Space: 512MB
Percent Used: 1%

Volume Groups Information
==============================================================================
Active VGs
==============================================================================
rootvg:
PV_NAME PV STATE TOTAL PPs FREE PPs FREE DISTRIBUTION
hdisk0 active 999 809 199..193..17..200..200
==============================================================================

INSTALLED RESOURCE LIST

The following resources are installed on the machine.
+/- = Added or deleted from Resource List.
* = Diagnostic support not available.

Model Architecture: chrp
Model Implementation: Uni-Processor, PCI bus

+ sys0 System Object
+ sysplanar0 System Planar
* vio0 Virtual I/O Bus
* ent0 Virtual I/O Ethernet Adapter (l-lan)
* vscsi0 Virtual SCSI Client Adapter
* cd0 Virtual SCSI Optical Served by VIO Server
* vsa0 LPAR Virtual Serial Adapter
* vty0 Asynchronous Terminal
* pci0 PCI Bus
* scsi0 qemu_virtio-scsi-pci:0000:00:02.0 Virtio SCSI Client Adapter (f41a0800)
* hdisk0 qemu_virtio-scsi-pci:0000:00:02.0-LW_0 MPIO Other Virtio SCSI Disk Drive
+ L2cache0 L2 Cache
+ mem0 Memory
+ proc0 Processor
+ proc1 Processor
+ proc2 Processor
+ proc3 Processor
11 changes: 11 additions & 0 deletions cpu/testdata/aix/sar-u-PALL101
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

AIX aix72-dylan 2 7 000000000000 05/15/24

System configuration: lcpu=4 ent=4.00 mode=Capped

11:19:03 cpu %usr %sys %wio %idle physc %entc
11:19:13 0 1 11 0 88 1.00 25.0
1 0 0 0 100 1.00 25.0
2 0 0 0 100 1.00 25.0
3 0 0 0 100 1.00 25.0
- 0 3 0 97 4.00 100.0
7 changes: 7 additions & 0 deletions cpu/testdata/aix/sar-u101
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

AIX aix72-dylan 2 7 000000000000 05/15/24

System configuration: lcpu=4 ent=4.00 mode=Capped

11:19:44 %usr %sys %wio %idle physc %entc
11:19:54 0 3 0 96 4.00 100.0
34 changes: 31 additions & 3 deletions disk/disk_aix.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package disk

import (
"context"
"errors"
"strings"

"github.com/shirou/gopsutil/v3/internal/common"
)
Expand All @@ -13,10 +15,36 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
return nil, common.ErrNotImplementedError
}

func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) {
return "", common.ErrNotImplementedError
}

func LabelWithContext(ctx context.Context, name string) (string, error) {
return "", common.ErrNotImplementedError
// Using lscfg and a device name, we can get the device information
// This is a pure go implementation, and should be moved to disk_aix_nocgo.go
// if a more efficient CGO method is introduced in disk_aix_cgo.go
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
// This isn't linux, these aren't actual disk devices
if strings.HasPrefix(name, "/dev/") {
return "", errors.New("devices on /dev are not physical disks on aix")
}
out, err := invoke.CommandWithContext(ctx, "lscfg", "-vl", name)
if err != nil {
return "", err
}

ret := ""
// Kind of inefficient, but it works
lines := strings.Split(string(out[:]), "\n")
for line := 1; line < len(lines); line++ {
v := strings.TrimSpace(lines[line])
if strings.HasPrefix(v, "Serial Number...............") {
ret = strings.TrimPrefix(v, "Serial Number...............")
if ret == "" {
return "", errors.New("empty serial for disk")
}
return ret, nil
}
}

return ret, errors.New("serial entry not found for disk")
}
Loading

0 comments on commit cb52f7a

Please sign in to comment.