Skip to content

Commit cb52f7a

Browse files
authored
Merge pull request #1651 from Dylan-M/aix_support
Improve AIX Support
2 parents 8912445 + 125da53 commit cb52f7a

14 files changed

+618
-84
lines changed

README.md

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ See https://pkg.go.dev/github.com/shirou/gopsutil/v3 or https://godocs.io/github
126126

127127
## Requirements
128128

129-
- go1.16 or above is required.
129+
- go1.18 or above is required.
130130

131131
## More Info
132132

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

185185
- x: works
186186
- b: almost works, but something is broken
187-
188-
|name |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |Plan 9 |
189-
|----------------------|-------|---------|---------|--------|---------|---------|---------|
190-
|cpu\_times |x |x |x |x |x | |b |
191-
|cpu\_count |x |x |x |x |x | |x |
192-
|cpu\_percent |x |x |x |x |x | | |
193-
|cpu\_times\_percent |x |x |x |x |x | | |
194-
|virtual\_memory |x |x |x |x |x | b |x |
195-
|swap\_memory |x |x |x |x | | |x |
196-
|disk\_partitions |x |x |x |x |x | | |
197-
|disk\_io\_counters |x |x |x | | | | |
198-
|disk\_usage |x |x |x |x |x | | |
199-
|net\_io\_counters |x |x |x |b |x | | |
200-
|boot\_time |x |x |x |x |x | | |
201-
|users |x |x |x |x |x | | |
202-
|pids |x |x |x |x |x | | |
203-
|pid\_exists |x |x |x |x |x | | |
204-
|net\_connections |x |x |x |x | | | |
205-
|net\_protocols |x | | | | | | |
206-
|net\_if\_addrs | | | | | | | |
207-
|net\_if\_stats | | | | | | | |
208-
|netfilter\_conntrack |x | | | | | | |
187+
- c: works in CGO only
188+
189+
|name |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |Plan 9 |AIX |
190+
|----------------------|-------|---------|---------|--------|---------|---------|---------|---------|
191+
|cpu\_times |x |x |x |x |x | |b |x |
192+
|cpu\_count |x |x |x |x |x | |x |x |
193+
|cpu\_percent |x |x |x |x |x | | |x |
194+
|cpu\_times\_percent |x |x |x |x |x | | |x |
195+
|virtual\_memory |x |x |x |x |x | b |x |x |
196+
|swap\_memory |x |x |x |x | | |x |X |
197+
|disk\_partitions |x |x |x |x |x | | |x |
198+
|disk\_io\_counters |x |x |x | | | | | |
199+
|disk\_usage |x |x |x |x |x | | |x |
200+
|net\_io\_counters |x |x |x |b |x | | | |
201+
|boot\_time |x |x |x |x |x | | |X |
202+
|users |x |x |x |x |x | | |x |
203+
|pids |x |x |x |x |x | | | |
204+
|pid\_exists |x |x |x |x |x | | | |
205+
|net\_connections |x |x |x |x | | | |x |
206+
|net\_protocols |x | | | | | | |x |
207+
|net\_if\_addrs | | | | | | | |x |
208+
|net\_if\_stats | | | | | | | |x |
209+
|netfilter\_conntrack |x | | | | | | | |
209210

210211

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

255256
### Original Metrics
256257

257-
|item |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |
258-
|-----------------|-------|---------|---------|--------|--------|---------|
259-
|**HostInfo** | | | | | | |
260-
|hostname |x |x |x |x |x |x |
261-
|uptime |x |x |x |x | |x |
262-
|process |x |x |x | | |x |
263-
|os |x |x |x |x |x |x |
264-
|platform |x |x |x |x | |x |
265-
|platformfamily |x |x |x |x | |x |
266-
|virtualization |x | | | | | |
267-
|**CPU** | | | | | | |
268-
|VendorID |x |x |x |x |x |x |
269-
|Family |x |x |x |x |x |x |
270-
|Model |x |x |x |x |x |x |
271-
|Stepping |x |x |x |x |x |x |
272-
|PhysicalID |x | | | | |x |
273-
|CoreID |x | | | | |x |
274-
|Cores |x | | | |x |x |
275-
|ModelName |x |x |x |x |x |x |
276-
|Microcode |x | | | | |x |
277-
|**LoadAvg** | | | | | | |
278-
|Load1 |x |x |x |x | | |
279-
|Load5 |x |x |x |x | | |
280-
|Load15 |x |x |x |x | | |
281-
|**GetDockerID** | | | | | | |
282-
|container id |x |no |no |no |no | |
283-
|**CgroupsCPU** | | | | | | |
284-
|user |x |no |no |no |no | |
285-
|system |x |no |no |no |no | |
286-
|**CgroupsMem** | | | | | | |
287-
|various |x |no |no |no |no | |
258+
|item |Linux |FreeBSD |OpenBSD |macOS |Windows |Solaris |AIX |
259+
|-----------------|-------|---------|---------|--------|--------|---------|---------|
260+
|**HostInfo** | | | | | | | |
261+
|hostname |x |x |x |x |x |x |X |
262+
|uptime |x |x |x |x | |x |x |
263+
|process |x |x |x | | |x | |
264+
|os |x |x |x |x |x |x |x |
265+
|platform |x |x |x |x | |x |x |
266+
|platformfamily |x |x |x |x | |x |x |
267+
|virtualization |x | | | | | | |
268+
|**CPU** | | | | | | | |
269+
|VendorID |x |x |x |x |x |x |x |
270+
|Family |x |x |x |x |x |x |x |
271+
|Model |x |x |x |x |x |x |x |
272+
|Stepping |x |x |x |x |x |x | |
273+
|PhysicalID |x | | | | |x | |
274+
|CoreID |x | | | | |x | |
275+
|Cores |x | | | |x |x |x |
276+
|ModelName |x |x |x |x |x |x |x |
277+
|Microcode |x | | | | |x | |
278+
|**LoadAvg** | | | | | | | |
279+
|Load1 |x |x |x |x | | |x |
280+
|Load5 |x |x |x |x | | |x |
281+
|Load15 |x |x |x |x | | |x |
282+
|**GetDockerID** | | | | | | | |
283+
|container id |x |no |no |no |no | | |
284+
|**CgroupsCPU** | | | | | | | |
285+
|user |x |no |no |no |no | | |
286+
|system |x |no |no |no |no | | |
287+
|**CgroupsMem** | | | | | | | |
288+
|various |x |no |no |no |no | | |
288289

289290
- future work
290291
- process_iter
291292
- wait_procs
292293
- Process class
293294
- as_dict
294295
- wait
296+
- AIX processes
295297

296298
## License
297299

cpu/cpu_aix_nocgo.go

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,57 @@ import (
1212
)
1313

1414
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
15+
var ret []TimesStat
1516
if percpu {
16-
return []TimesStat{}, common.ErrNotImplementedError
17+
per_out, err := invoke.CommandWithContext(ctx, "sar", "-u", "-P", "ALL", "10", "1")
18+
if err != nil {
19+
return nil, err
20+
}
21+
lines := strings.Split(string(per_out), "\n")
22+
if len(lines) < 6 {
23+
return []TimesStat{}, common.ErrNotImplementedError
24+
}
25+
26+
hp := strings.Fields(lines[5]) // headers
27+
for l := 6; l < len(lines)-1; l++ {
28+
ct := &TimesStat{}
29+
v := strings.Fields(lines[l]) // values
30+
for i, header := range hp {
31+
// We're done in any of these use cases
32+
if i >= len(v) || v[0] == "-" {
33+
break
34+
}
35+
36+
// Position variable for v
37+
pos := i
38+
// There is a missing field at the beginning of all but the first line
39+
// so adjust the position
40+
if l > 6 {
41+
pos = i - 1
42+
}
43+
// We don't want invalid positions
44+
if pos < 0 {
45+
continue
46+
}
47+
48+
if t, err := strconv.ParseFloat(v[pos], 64); err == nil {
49+
switch header {
50+
case `cpu`:
51+
ct.CPU = strconv.FormatFloat(t, 'f', -1, 64)
52+
case `%usr`:
53+
ct.User = t
54+
case `%sys`:
55+
ct.System = t
56+
case `%wio`:
57+
ct.Iowait = t
58+
case `%idle`:
59+
ct.Idle = t
60+
}
61+
}
62+
}
63+
// Valid CPU data, so append it
64+
ret = append(ret, *ct)
65+
}
1766
} else {
1867
out, err := invoke.CommandWithContext(ctx, "sar", "-u", "10", "1")
1968
if err != nil {
@@ -24,26 +73,28 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
2473
return []TimesStat{}, common.ErrNotImplementedError
2574
}
2675

27-
ret := TimesStat{CPU: "cpu-total"}
76+
ct := &TimesStat{CPU: "cpu-total"}
2877
h := strings.Fields(lines[len(lines)-3]) // headers
2978
v := strings.Fields(lines[len(lines)-2]) // values
3079
for i, header := range h {
3180
if t, err := strconv.ParseFloat(v[i], 64); err == nil {
3281
switch header {
3382
case `%usr`:
34-
ret.User = t
83+
ct.User = t
3584
case `%sys`:
36-
ret.System = t
85+
ct.System = t
3786
case `%wio`:
38-
ret.Iowait = t
87+
ct.Iowait = t
3988
case `%idle`:
40-
ret.Idle = t
89+
ct.Idle = t
4190
}
4291
}
4392
}
4493

45-
return []TimesStat{ret}, nil
94+
ret = append(ret, *ct)
4695
}
96+
97+
return ret, nil
4798
}
4899

49100
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
@@ -78,6 +129,20 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
78129
}
79130
}
80131
break
132+
} else if strings.HasPrefix(line, "System Model:") {
133+
p := strings.Split(string(line), ":")
134+
if p != nil {
135+
ret.VendorID = strings.TrimSpace(p[1])
136+
}
137+
} else if strings.HasPrefix(line, "Processor Type:") {
138+
p := strings.Split(string(line), ":")
139+
if p != nil {
140+
c := strings.Split(string(p[1]), "_")
141+
if c != nil {
142+
ret.Family = strings.TrimSpace(c[0])
143+
ret.Model = strings.TrimSpace(c[1])
144+
}
145+
}
81146
}
82147
}
83148
return []InfoStat{ret}, nil

cpu/testdata/aix/prtconf

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
System Model: IBM pSeries (emulated by qemu)
2+
Machine Serial Number: Not Available
3+
Processor Type: PowerPC_POWER8
4+
Processor Implementation Mode: POWER 8
5+
Processor Version: PV_8_Compat
6+
Number Of Processors: 4
7+
Processor Clock Speed: 1000 MHz
8+
CPU Type: 64-bit
9+
Kernel Type: 64-bit
10+
LPAR Info: 0 aix_7200-04-02-2027
11+
Memory Size: 4096 MB
12+
Good Memory Size: 4096 MB
13+
Platform Firmware level: Not Available
14+
Firmware Version: SLOF,HEAD
15+
Console Login: enable
16+
Auto Restart: true
17+
Full Core: false
18+
NX Crypto Acceleration: Not Capable
19+
In-Core Crypto Acceleration: Capable, but not Enabled
20+
21+
en0
22+
Network Information
23+
Host Name: aix72-dylan
24+
IP Address: 192.168.124.53
25+
Sub Netmask:
26+
Gateway: 192.168.124.1
27+
Name Server:
28+
Domain Name:
29+
30+
Paging Space Information
31+
Total Paging Space: 512MB
32+
Percent Used: 1%
33+
34+
Volume Groups Information
35+
==============================================================================
36+
Active VGs
37+
==============================================================================
38+
rootvg:
39+
PV_NAME PV STATE TOTAL PPs FREE PPs FREE DISTRIBUTION
40+
hdisk0 active 999 809 199..193..17..200..200
41+
==============================================================================
42+
43+
INSTALLED RESOURCE LIST
44+
45+
The following resources are installed on the machine.
46+
+/- = Added or deleted from Resource List.
47+
* = Diagnostic support not available.
48+
49+
Model Architecture: chrp
50+
Model Implementation: Uni-Processor, PCI bus
51+
52+
+ sys0 System Object
53+
+ sysplanar0 System Planar
54+
* vio0 Virtual I/O Bus
55+
* ent0 Virtual I/O Ethernet Adapter (l-lan)
56+
* vscsi0 Virtual SCSI Client Adapter
57+
* cd0 Virtual SCSI Optical Served by VIO Server
58+
* vsa0 LPAR Virtual Serial Adapter
59+
* vty0 Asynchronous Terminal
60+
* pci0 PCI Bus
61+
* scsi0 qemu_virtio-scsi-pci:0000:00:02.0 Virtio SCSI Client Adapter (f41a0800)
62+
* hdisk0 qemu_virtio-scsi-pci:0000:00:02.0-LW_0 MPIO Other Virtio SCSI Disk Drive
63+
+ L2cache0 L2 Cache
64+
+ mem0 Memory
65+
+ proc0 Processor
66+
+ proc1 Processor
67+
+ proc2 Processor
68+
+ proc3 Processor

cpu/testdata/aix/sar-u-PALL101

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
AIX aix72-dylan 2 7 000000000000 05/15/24
3+
4+
System configuration: lcpu=4 ent=4.00 mode=Capped
5+
6+
11:19:03 cpu %usr %sys %wio %idle physc %entc
7+
11:19:13 0 1 11 0 88 1.00 25.0
8+
1 0 0 0 100 1.00 25.0
9+
2 0 0 0 100 1.00 25.0
10+
3 0 0 0 100 1.00 25.0
11+
- 0 3 0 97 4.00 100.0

cpu/testdata/aix/sar-u101

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
AIX aix72-dylan 2 7 000000000000 05/15/24
3+
4+
System configuration: lcpu=4 ent=4.00 mode=Capped
5+
6+
11:19:44 %usr %sys %wio %idle physc %entc
7+
11:19:54 0 3 0 96 4.00 100.0

disk/disk_aix.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package disk
55

66
import (
77
"context"
8+
"errors"
9+
"strings"
810

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

16-
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
18+
func LabelWithContext(ctx context.Context, name string) (string, error) {
1719
return "", common.ErrNotImplementedError
1820
}
1921

20-
func LabelWithContext(ctx context.Context, name string) (string, error) {
21-
return "", common.ErrNotImplementedError
22+
// Using lscfg and a device name, we can get the device information
23+
// This is a pure go implementation, and should be moved to disk_aix_nocgo.go
24+
// if a more efficient CGO method is introduced in disk_aix_cgo.go
25+
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
26+
// This isn't linux, these aren't actual disk devices
27+
if strings.HasPrefix(name, "/dev/") {
28+
return "", errors.New("devices on /dev are not physical disks on aix")
29+
}
30+
out, err := invoke.CommandWithContext(ctx, "lscfg", "-vl", name)
31+
if err != nil {
32+
return "", err
33+
}
34+
35+
ret := ""
36+
// Kind of inefficient, but it works
37+
lines := strings.Split(string(out[:]), "\n")
38+
for line := 1; line < len(lines); line++ {
39+
v := strings.TrimSpace(lines[line])
40+
if strings.HasPrefix(v, "Serial Number...............") {
41+
ret = strings.TrimPrefix(v, "Serial Number...............")
42+
if ret == "" {
43+
return "", errors.New("empty serial for disk")
44+
}
45+
return ret, nil
46+
}
47+
}
48+
49+
return ret, errors.New("serial entry not found for disk")
2250
}

0 commit comments

Comments
 (0)