Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve AIX Support #1651

Merged
merged 23 commits into from
May 27, 2024
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6b630a8
Add support for per CPU
May 15, 2024
8cc3269
Add support for additional CPU info fields
May 15, 2024
af3f4d2
Correct arguments for AIX percpu
May 15, 2024
d816d96
Initial pass at AIX test integration
May 15, 2024
843d93a
Add AIX test data
May 15, 2024
0a1f220
Remove tests, since my Go knowledge isn't yet deep enough for them
May 15, 2024
5d3cf2e
Update AIX percpu minimum needed lines
May 15, 2024
52d61b8
Add host support for AIX
May 16, 2024
d551997
Fix typos and code misplacement in AIX CPU handling
May 16, 2024
bd42769
Add a working implementation of host.Users() for AIX
May 16, 2024
9be5f7d
Remove extraneous -1 from users function for AIX
May 16, 2024
ea8f72e
Add Usage for AIX nocgo
May 16, 2024
3bf34ce
Add AIX disk serial numbers for nocgo
May 17, 2024
a0bbcca
Only handle virtual memory when specifically requested
May 17, 2024
8df2696
Account for other possible formats output by AIX uptime command
May 18, 2024
0917790
Remove inappropriate package addition
May 18, 2024
b4d95a4
Raise minimum go version to 1.18 (required by changes) and run go mod…
May 18, 2024
b133d60
Ignore host_aix_ppc64 for now
May 18, 2024
9bf502f
Fix logic errors, syntax errors, and typos
May 18, 2024
1d7b4a3
Revert accidental change of go version in go.mod (wasn't supposed to …
May 18, 2024
df9c9bf
Update min version in the readme to match new required min version.
May 21, 2024
ff4ae36
Remove extraneous development note comments
May 22, 2024
125da53
Update the README charts with the AIX information
May 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix logic errors, syntax errors, and typos
Dylan Myers committed May 18, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 9bf502f825346c8930c945ddc8f892ec3bc1c3e2
2 changes: 1 addition & 1 deletion cpu/cpu_aix_nocgo.go
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
if t, err := strconv.ParseFloat(v[pos], 64); err == nil {
switch header {
case `cpu`:
ct.CPU = t
ct.CPU = strconv.FormatFloat(t, 'f', -1, 64)
case `%usr`:
ct.User = t
case `%sys`:
43 changes: 23 additions & 20 deletions disk/disk_aix_nocgo.go
Original file line number Diff line number Diff line change
@@ -83,22 +83,22 @@ func getFsType(stat unix.Statfs_t) string {
}

func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
Dylan-M marked this conversation as resolved.
Show resolved Hide resolved
var ret []UsageStat
out, err := invoke.CommandWithContext(ctx, "df", "-v")
if err != nil {
return nil, err
}

ret := &UsageStat{}

blocksize := uint64(512)
lines := strings.Split(string(out), "\n")
if len(lines) < 2 {
return []UsageStat{}, common.ErrNotImplementedError
return &UsageStat{}, common.ErrNotImplementedError
}

hf := strings.Fields(strings.Replace(lines[0], "Mounted on", "Path", -1)) // headers
for line := 1; line < len(lines); line++ {
fs := strings.Fields(lines[line]) // values
us := &UsageStat{}
for i, header := range hf {
// We're done in any of these use cases
if i >= len(fs) {
@@ -108,65 +108,68 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
switch header {
case `Filesystem`:
// This is not a valid fs for us to parse
if fs[i] == "/proc" || fs[i] == "/ahafs" {
continue
if fs[i] == "/proc" || fs[i] == "/ahafs" || fs[i] != path {
break
}

us.Fstype, err = GetMountFSType(fs[i])
ret.Fstype, err = GetMountFSTypeWithContext(ctx, fs[i])
if err != nil {
return nil, err
}
case `Path`:
us.Path = fs[i]
ret.Path = fs[i]
case `512-blocks`:
us.Total, err = strconv.Atoi(fs[i])
total, err := strconv.ParseUint(fs[i], 10, 64)
ret.Total = total * blocksize
if err != nil {
return nil, err
}
case `Used`:
us.Used, err = strconv.Atoi(fs[i])
ret.Used, err = strconv.ParseUint(fs[i], 10, 64)
if err != nil {
return nil, err
}
case `Free`:
us.Free, err = strconv.Atoi(fs[i])
ret.Free, err = strconv.ParseUint(fs[i], 10, 64)
if err != nil {
return nil, err
}
case `%Used`:
us.UsedPercent, err = strconv.ParseFloat(fs[i])
val, err := strconv.Atoi(strings.Replace(fs[i], "%", "", -1))
if err != nil {
return nil, err
}
ret.UsedPercent = float64(val) / float64(100)
case `Ifree`:
us.InodesFree, err = strconv.Atoi(fs[i])
ret.InodesFree, err = strconv.ParseUint(fs[i], 10, 64)
if err != nil {
return nil, err
}
case `Iused`:
us.InodesUsed, err = strconv.Atoi(fs[i])
ret.InodesUsed, err = strconv.ParseUint(fs[i], 10, 64)
if err != nil {
return nil, err
}
case `%Iused`:
us.InodesUsedPercent, err = strconv.ParseFloat(fs[i])
val, err := strconv.Atoi(strings.Replace(fs[i], "%", "", -1))
if err != nil {
return nil, err
}
ret.InodesUsedPercent = float64(val) / float64(100)
}
}

// Calculated value, since it isn't returned by the command
us.InodesTotal = us.InodesUsed + us.InodesFree
ret.InodesTotal = ret.InodesUsed + ret.InodesFree

// Valid Usage data, so append it
ret = append(ret, *us)
return ret, nil
}

return *ret, nil
return ret, nil
}

func GetMountFSType(mp string) (string, error) {
func GetMountFSTypeWithContext(ctx context.Context, mp string) (string, error) {
out, err := invoke.CommandWithContext(ctx, "mount")
if err != nil {
return "", err
@@ -212,11 +215,11 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
if strings.HasPrefix(v, "Serial Number...............") {
ret = strings.TrimPrefix(v, "Serial Number...............")
if ret == "" {
return "", errors.New("empty eerial for disk")
return "", errors.New("empty serial for disk")
}
return ret, nil
}
}

sreturn ret, errors.New("serial entry not found for disk")
return ret, errors.New("serial entry not found for disk")
}
4 changes: 2 additions & 2 deletions disk/disk_unix.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build freebsd || linux || darwin || (aix && !cgo)
// +build freebsd linux darwin aix,!cgo
//go:build freebsd || linux || darwin
// +build freebsd linux darwin

package disk

43 changes: 23 additions & 20 deletions host/host_aix.go
Original file line number Diff line number Diff line change
@@ -26,11 +26,11 @@ func HostIDWithContext(ctx context.Context) (string, error) {
}

// The command always returns an extra newline, so we make use of Split() to get only the first line
return strings.Split(string(out[:]), "\n")[0]
return strings.Split(string(out[:]), "\n")[0], nil
}

func numProcs(ctx context.Context) (uint64, error) {
return common.NumProcsWithContext(ctx)
return 0, common.ErrNotImplementedError
}

func BootTimeWithContext(ctx context.Context) (btime uint64, err error) {
@@ -52,7 +52,7 @@ func BootTimeWithContext(ctx context.Context) (btime uint64, err error) {
//07:43PM up 5 hrs, 1 user, load average: 3.27, 2.91, 2.72
//11:18:23 up 83 days, 18:29, 4 users, load average: 0.16, 0.03, 0.01
func UptimeWithContext(ctx context.Context) (uint64, error) {
out, err := invoke.CommandWithContext(ctx, "uptime").Output()
out, err := invoke.CommandWithContext(ctx, "uptime")
if err != nil {
return 0, err
}
@@ -112,7 +112,7 @@ func UptimeWithContext(ctx context.Context) (uint64, error) {
// This is a weak implementation due to the limitations on retrieving this data in AIX
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
var ret []UserStat
out, err := invoke.CommandWithContext(ctx, "w").Output()
out, err := invoke.CommandWithContext(ctx, "w")
if err != nil {
return nil, err
}
@@ -134,9 +134,9 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
if t, err := strconv.ParseFloat(v[i], 64); err == nil {
switch header {
case `User`:
us.User = t
us.User = strconv.FormatFloat(t, 'f', 1, 64)
case `tty`:
us.Terminal = t
us.Terminal = strconv.FormatFloat(t, 'f', 1, 64)
}
}
}
@@ -151,46 +151,49 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
// Much of this function could be static. However, to be future proofed, I've made it call the OS for the information in all instances.
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
// Set the platform (which should always, and only be, "AIX") from `uname -s`
out, err := invoke.CommandWithContext(ctx, "uname", "-s").Output()
out, err := invoke.CommandWithContext(ctx, "uname", "-s")
if err != nil {
return "", "", "", err
}
platform = string(out[:])
platform = strings.TrimRight(string(out[:]), "\n")

// Set the family
out, err = invoke.CommandWithContext(ctx, "bootinfo", "-p").Output()
if err != nil {
return "", "", "", err
}
// Family seems to always be the second field from this uname, so pull that out
family = string(out[:])
family = strings.TrimRight(string(out[:]), "\n")

// Set the version
out, err = invoke.CommandWithContext(ctx, "oslevel").Output()
out, err = invoke.CommandWithContext(ctx, "oslevel")
if err != nil {
return "", "", "", err
}
version = string(out[:])
version = strings.TrimRight(string(out[:]), "\n")

return platform, family, version, nil
}

func KernelVersionWithContext(ctx context.Context) (version string, err error) {
out, err := invoke.CommandWithContext(ctx, "oslevel", "-s").Output()
out, err := invoke.CommandWithContext(ctx, "oslevel", "-s")
if err != nil {
return "", err
}
version = string(out[:])
version = strings.TrimRight(string(out[:]), "\n")

return version, nil
}

func KernelArch() (arch string, err error) {
out, err := invoke.CommandWithContext(ctx, "bootinfo", "-y").Output()
out, err := invoke.Command("bootinfo", "-y")
if err != nil {
return "", err
}
arch = string(out[:])
arch = strings.TrimRight(string(out[:]), "\n")

return arch, nil
}

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

func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return nil, common.ErrNotImplementedError
}
4 changes: 2 additions & 2 deletions host/host_fallback.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build !darwin && !linux && !freebsd && !openbsd && !netbsd && !solaris && !windows
// +build !darwin,!linux,!freebsd,!openbsd,!netbsd,!solaris,!windows
//go:build !darwin && !linux && !freebsd && !openbsd && !netbsd && !solaris && !windows && !aix
// +build !darwin,!linux,!freebsd,!openbsd,!netbsd,!solaris,!windows,!aix

package host