Add host support for AIX

pull/1651/head
Dylan Myers 10 months ago
parent 5d3cf2e9e7
commit 52d61b8669

@ -0,0 +1,158 @@
//go:build aix
// +build aix
package host
import (
"bytes"
"context"
"encoding/binary"
"errors"
"strconv"
"strings"
"github.com/shirou/gopsutil/v3/internal/common"
)
// from https://www.ibm.com/docs/en/aix/7.2?topic=files-utmph-file
const (
user_PROCESS = 7
hostTemperatureScale = 1000.0 // Not part of the linked file, but kept just in case it becomes relevant
)
func HostIDWithContext(ctx context.Context) (string, error) {
out, err := invoke.CommandWithContext(ctx, "uname", "-u")
if err != nil {
return "", err
}
// 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]
}
func numProcs(ctx context.Context) (uint64, error) {
return common.NumProcsWithContext(ctx)
}
func BootTimeWithContext(ctx context.Context) (btime uint64, err error) {
ut, err := UptimeWithContext(ctx)
if err != nil {
return 0, err
}
if ut <= 0 {
return 0, errors.New("Uptime was not set, so cannot calculate boot time from it.")
}
ut = ut * 60
return timeSince(ut), nil
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
out, err := invoke.CommandWithContext(ctx, "uptime").Output()
if err != nil {
return 0, err
}
// Convert our uptime to a series of fields we can extract
ut := strings.Fields(string(out[:]))
// Convert the second field "Days" value to integer and roll it to minutes
days, err := strconv.Atoi(ut[2])
if err != nil {
return 0, err
}
// Split field 4 into hours and minutes
hm := strings.Split(ut[4], ":")
hours, err := strconv.Atoi(hm[0])
if err != nil {
return 0, err
}
minutes, err := strconv.Atoi(strings.Replace(hm[1], ",", "", -1))
if err != nil {
return 0, err
}
// Stack them all together as minutes
total_time := (days * 24 * 60) + (hours * 60) + minutes
return uint64(total_time), nil
}
// This is probably broken, it doesn't seem to work even with CGO
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
var ret []UserStat
ut, err := invoke.CommandWithContext(ctx, "w").Output()
for i := 0; i < count; i++ {
b := buf[i*sizeOfUtmp : (i+1)*sizeOfUtmp]
var u utmp
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil {
continue
}
if u.Type != user_PROCESS {
continue
}
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Tv.Sec),
}
ret = append(ret, user)
}
return ret, nil
}
// 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()
if err != nil {
return "", "", "", err
}
platform = string(out[:])
// 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[:])
// Set the version
out, err = invoke.CommandWithContext(ctx, "oslevel").Output()
if err != nil {
return "", "", "", err
}
version = string(out[:])
return platform, family, version, nil
}
func KernelVersionWithContext(ctx context.Context) (version string, err error) {
out, err := invoke.CommandWithContext(ctx, "oslevel", "-s").Output()
if err != nil {
return "", err
}
version = string(out[:])
return version, nil
}
func KernelArch() (arch string, err error) {
out, err := invoke.CommandWithContext(ctx, "bootinfo", "-y").Output()
if err != nil {
return "", err
}
arch = string(out[:])
return arch, nil
}

@ -0,0 +1,48 @@
//go:build aix && ppc64
// +build aix,ppc64
// Guessed at from the following document:
// https://www.ibm.com/docs/sl/ibm-mq/9.2?topic=platforms-standard-data-types-aix-linux-windows
package host
const (
sizeofPtr = 0x
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x180
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type utmp struct {
Type int16
Pad_cgo_0 [2]byte
Pid int32
Line [32]int8
Id [4]int8
User [32]int8
Host [256]int8
Exit exit_status
Session int32
Tv timeval
Addr_v6 [4]int32
X__glibc_reserved [20]int8
}
type exit_status struct {
Termination int16
Exit int16
}
type timeval struct {
Sec int64
Usec int64
}
Loading…
Cancel
Save