diff --git a/host/host.go b/host/host.go index e100bc5..647cf01 100644 --- a/host/host.go +++ b/host/host.go @@ -1,7 +1,11 @@ package host import ( + "context" "encoding/json" + "os" + "runtime" + "time" "github.com/shirou/gopsutil/internal/common" ) @@ -52,3 +56,99 @@ func (t TemperatureStat) String() string { s, _ := json.Marshal(t) return string(s) } + +func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { + var err error + ret := &InfoStat{ + OS: runtime.GOOS, + } + + ret.Hostname, err = os.Hostname() + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.Platform, ret.PlatformFamily, ret.PlatformVersion, err = PlatformInformationWithContext(ctx) + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.KernelVersion, err = KernelVersionWithContext(ctx) + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.KernelArch, err = KernelArch() + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.VirtualizationSystem, ret.VirtualizationRole, err = VirtualizationWithContext(ctx) + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.BootTime, err = BootTimeWithContext(ctx) + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.Uptime, err = UptimeWithContext(ctx) + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.Procs, err = numProcs(ctx) + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + ret.HostID, err = HostIDWithContext(ctx) + if err != nil && err != common.ErrNotImplementedError { + return nil, err + } + + return ret, nil +} + +// BootTime returns the system boot time expressed in seconds since the epoch. +func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func PlatformInformation() (string, string, string, error) { + return PlatformInformationWithContext(context.Background()) +} + +// HostID returns the unique host ID provided by the OS. +func HostID() (string, error) { + return HostIDWithContext(context.Background()) +} + +func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func KernelVersion() (string, error) { + return KernelVersionWithContext(context.Background()) +} + +func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func timeSince(ts uint64) uint64 { + return uint64(time.Now().Unix()) - ts +} diff --git a/host/host_bsd.go b/host/host_bsd.go index 7c49e6a..fc45b87 100644 --- a/host/host_bsd.go +++ b/host/host_bsd.go @@ -5,7 +5,6 @@ package host import ( "context" "sync/atomic" - "time" "golang.org/x/sys/unix" ) @@ -13,10 +12,6 @@ import ( // cachedBootTime must be accessed via atomic.Load/StoreUint64 var cachedBootTime uint64 -func BootTime() (uint64, error) { - return BootTimeWithContext(context.Background()) -} - func BootTimeWithContext(ctx context.Context) (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { @@ -32,18 +27,10 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) { return uint64(tv.Sec), nil } -func uptime(boot uint64) uint64 { - return uint64(time.Now().Unix()) - boot -} - -func Uptime() (uint64, error) { - return UptimeWithContext(context.Background()) -} - func UptimeWithContext(ctx context.Context) (uint64, error) { boot, err := BootTimeWithContext(ctx) if err != nil { return 0, err } - return uptime(boot), nil + return timeSince(boot), nil } diff --git a/host/host_darwin.go b/host/host_darwin.go index e2d576e..8f51b20 100644 --- a/host/host_darwin.go +++ b/host/host_darwin.go @@ -9,7 +9,6 @@ import ( "io/ioutil" "os" "os/exec" - "runtime" "strings" "unsafe" @@ -21,65 +20,20 @@ import ( // from utmpx.h const USER_PROCESS = 7 -func Info() (*InfoStat, error) { - return InfoWithContext(context.Background()) -} - -func InfoWithContext(ctx context.Context) (*InfoStat, error) { - ret := &InfoStat{ - OS: runtime.GOOS, - PlatformFamily: "darwin", - } - - hostname, err := os.Hostname() - if err == nil { - ret.Hostname = hostname - } - - kernelVersion, err := KernelVersionWithContext(ctx) - if err == nil { - ret.KernelVersion = kernelVersion - } - - kernelArch, err := kernelArch() - if err == nil { - ret.KernelArch = kernelArch - } - - platform, family, pver, err := PlatformInformation() - if err == nil { - ret.Platform = platform - ret.PlatformFamily = family - ret.PlatformVersion = pver - } - - system, role, err := Virtualization() - if err == nil { - ret.VirtualizationSystem = system - ret.VirtualizationRole = role - } - - boot, err := BootTime() - if err == nil { - ret.BootTime = boot - ret.Uptime = uptime(boot) - } - - procs, err := process.Pids() - if err == nil { - ret.Procs = uint64(len(procs)) - } - +func HostIDWithContext(ctx context.Context) (string, error) { uuid, err := unix.Sysctl("kern.uuid") - if err == nil && uuid != "" { - ret.HostID = strings.ToLower(uuid) + if err != nil { + return "", err } - - return ret, nil + return strings.ToLower(uuid), err } -func Users() ([]UserStat, error) { - return UsersWithContext(context.Background()) +func numProcs(ctx context.Context) (uint64, error) { + procs, err := process.PidsWithContext(ctx) + if err != nil { + return 0, err + } + return uint64(len(procs)), nil } func UsersWithContext(ctx context.Context) ([]UserStat, error) { @@ -126,10 +80,6 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) { } -func PlatformInformation() (string, string, string, error) { - return PlatformInformationWithContext(context.Background()) -} - func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { platform := "" family := "" @@ -163,18 +113,10 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string return platform, family, pver, nil } -func Virtualization() (string, string, error) { - return VirtualizationWithContext(context.Background()) -} - func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } -func KernelVersion() (string, error) { - return KernelVersionWithContext(context.Background()) -} - func KernelVersionWithContext(ctx context.Context) (string, error) { version, err := unix.Sysctl("kern.osrelease") return strings.ToLower(version), err diff --git a/host/host_darwin_cgo.go b/host/host_darwin_cgo.go index 9b3b1c4..d5ba4cd 100644 --- a/host/host_darwin_cgo.go +++ b/host/host_darwin_cgo.go @@ -8,10 +8,6 @@ package host import "C" import "context" -func SensorsTemperatures() ([]TemperatureStat, error) { - return SensorsTemperaturesWithContext(context.Background()) -} - func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { temperatureKeys := []string{ C.AMBIENT_AIR_0, diff --git a/host/host_darwin_nocgo.go b/host/host_darwin_nocgo.go index 7869f8c..784899b 100644 --- a/host/host_darwin_nocgo.go +++ b/host/host_darwin_nocgo.go @@ -9,10 +9,6 @@ import ( "github.com/shirou/gopsutil/internal/common" ) -func SensorsTemperatures() ([]TemperatureStat, error) { - return SensorsTemperaturesWithContext(context.Background()) -} - func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } diff --git a/host/host_fallback.go b/host/host_fallback.go index e80d7ea..db697a5 100644 --- a/host/host_fallback.go +++ b/host/host_fallback.go @@ -8,58 +8,42 @@ import ( "github.com/shirou/gopsutil/internal/common" ) -func Info() (*InfoStat, error) { - return InfoWithContext(context.Background()) -} - -func InfoWithContext(ctx context.Context) (*InfoStat, error) { - return nil, common.ErrNotImplementedError +func HostIDWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError } -func BootTime() (uint64, error) { - return BootTimeWithContext(context.Background()) +func numProcs(ctx context.Context) (uint64, error) { + return 0, common.ErrNotImplementedError } func BootTimeWithContext(ctx context.Context) (uint64, error) { return 0, common.ErrNotImplementedError } -func Uptime() (uint64, error) { - return UptimeWithContext(context.Background()) -} - func UptimeWithContext(ctx context.Context) (uint64, error) { return 0, common.ErrNotImplementedError } -func Users() ([]UserStat, error) { - return UsersWithContext(context.Background()) -} - func UsersWithContext(ctx context.Context) ([]UserStat, error) { return []UserStat{}, common.ErrNotImplementedError } -func Virtualization() (string, string, error) { - return VirtualizationWithContext(context.Background()) -} - func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } -func KernelVersion() (string, error) { - return KernelVersionWithContext(context.Background()) -} - func KernelVersionWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } -func PlatformInformation() (string, string, string, error) { - return PlatformInformationWithContext(context.Background()) -} - func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { return "", "", "", common.ErrNotImplementedError } + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { + return []TemperatureStat{}, common.ErrNotImplementedError +} + +func KernelArch() (string, error) { + return "", common.ErrNotImplementedError +} diff --git a/host/host_freebsd.go b/host/host_freebsd.go index c5457c5..583a1f9 100644 --- a/host/host_freebsd.go +++ b/host/host_freebsd.go @@ -9,7 +9,6 @@ import ( "io/ioutil" "math" "os" - "runtime" "strings" "unsafe" @@ -24,61 +23,20 @@ const ( UTHostSize = 16 ) -func Info() (*InfoStat, error) { - return InfoWithContext(context.Background()) -} - -func InfoWithContext(ctx context.Context) (*InfoStat, error) { - ret := &InfoStat{ - OS: runtime.GOOS, - PlatformFamily: "freebsd", - } - - hostname, err := os.Hostname() - if err == nil { - ret.Hostname = hostname - } - - platform, family, version, err := PlatformInformation() - if err == nil { - ret.Platform = platform - ret.PlatformFamily = family - ret.PlatformVersion = version - ret.KernelVersion = version - } - - kernelArch, err := kernelArch() - if err == nil { - ret.KernelArch = kernelArch - } - - system, role, err := Virtualization() - if err == nil { - ret.VirtualizationSystem = system - ret.VirtualizationRole = role - } - - boot, err := BootTime() - if err == nil { - ret.BootTime = boot - ret.Uptime = uptime(boot) - } - - procs, err := process.Pids() - if err == nil { - ret.Procs = uint64(len(procs)) - } - - hostid, err := unix.Sysctl("kern.hostuuid") - if err == nil && hostid != "" { - ret.HostID = strings.ToLower(hostid) +func HostIDWithContext(ctx context.Context) (string, error) { + uuid, err := unix.Sysctl("kern.hostuuid") + if err != nil { + return "", err } - - return ret, nil + return strings.ToLower(uuid), err } -func Users() ([]UserStat, error) { - return UsersWithContext(context.Background()) +func numProcs(ctx context.Context) (uint64, error) { + procs, err := process.PidsWithContext(ctx) + if err != nil { + return 0, err + } + return uint64(len(procs)), nil } func UsersWithContext(ctx context.Context) ([]UserStat, error) { @@ -126,10 +84,6 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) { } -func PlatformInformation() (string, string, string, error) { - return PlatformInformationWithContext(context.Background()) -} - func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { platform, err := unix.Sysctl("kern.ostype") if err != nil { @@ -144,10 +98,6 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string return strings.ToLower(platform), "", strings.ToLower(version), nil } -func Virtualization() (string, string, error) { - return VirtualizationWithContext(context.Background()) -} - func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } @@ -191,19 +141,11 @@ func getUsersFromUtmp(utmpfile string) ([]UserStat, error) { return ret, nil } -func SensorsTemperatures() ([]TemperatureStat, error) { - return SensorsTemperaturesWithContext(context.Background()) -} - func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } -func KernelVersion() (string, error) { - return KernelVersionWithContext(context.Background()) -} - func KernelVersionWithContext(ctx context.Context) (string, error) { - _, _, version, err := PlatformInformation() + _, _, version, err := PlatformInformationWithContext(ctx) return version, err } diff --git a/host/host_linux.go b/host/host_linux.go index 6c76f90..29cadce 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -12,10 +12,8 @@ import ( "os/exec" "path/filepath" "regexp" - "runtime" "strconv" "strings" - "time" "github.com/shirou/gopsutil/internal/common" "golang.org/x/sys/unix" @@ -31,52 +29,7 @@ type LSB struct { // from utmp.h const USER_PROCESS = 7 -func Info() (*InfoStat, error) { - return InfoWithContext(context.Background()) -} - -func InfoWithContext(ctx context.Context) (*InfoStat, error) { - ret := &InfoStat{ - OS: runtime.GOOS, - } - - hostname, err := os.Hostname() - if err == nil { - ret.Hostname = hostname - } - - platform, family, version, err := PlatformInformation() - if err == nil { - ret.Platform = platform - ret.PlatformFamily = family - ret.PlatformVersion = version - } - kernelVersion, err := KernelVersion() - if err == nil { - ret.KernelVersion = kernelVersion - } - - kernelArch, err := kernelArch() - if err == nil { - ret.KernelArch = kernelArch - } - - system, role, err := Virtualization() - if err == nil { - ret.VirtualizationSystem = system - ret.VirtualizationRole = role - } - - boot, err := BootTime() - if err == nil { - ret.BootTime = boot - ret.Uptime = uptime(boot) - } - - if numProcs, err := common.NumProcs(); err == nil { - ret.Procs = numProcs - } - +func HostIDWithContext(ctx context.Context) (string, error) { sysProductUUID := common.HostSys("class/dmi/id/product_uuid") machineID := common.HostEtc("machine-id") procSysKernelRandomBootID := common.HostProc("sys/kernel/random/boot_id") @@ -86,8 +39,7 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { case common.PathExists(sysProductUUID): lines, err := common.ReadLines(sysProductUUID) if err == nil && len(lines) > 0 && lines[0] != "" { - ret.HostID = strings.ToLower(lines[0]) - break + return strings.ToLower(lines[0]), nil } fallthrough // Fallback on GNU Linux systems with systemd, readable by everyone @@ -95,48 +47,34 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { lines, err := common.ReadLines(machineID) if err == nil && len(lines) > 0 && len(lines[0]) == 32 { st := lines[0] - ret.HostID = fmt.Sprintf("%s-%s-%s-%s-%s", st[0:8], st[8:12], st[12:16], st[16:20], st[20:32]) - break + return fmt.Sprintf("%s-%s-%s-%s-%s", st[0:8], st[8:12], st[12:16], st[16:20], st[20:32]), nil } fallthrough // Not stable between reboot, but better than nothing default: lines, err := common.ReadLines(procSysKernelRandomBootID) if err == nil && len(lines) > 0 && lines[0] != "" { - ret.HostID = strings.ToLower(lines[0]) + return strings.ToLower(lines[0]), nil } } - return ret, nil + return "", nil } -// BootTime returns the system boot time expressed in seconds since the epoch. -func BootTime() (uint64, error) { - return BootTimeWithContext(context.Background()) +func numProcs(ctx context.Context) (uint64, error) { + return common.NumProcs() } func BootTimeWithContext(ctx context.Context) (uint64, error) { return common.BootTimeWithContext(ctx) } -func uptime(boot uint64) uint64 { - return uint64(time.Now().Unix()) - boot -} - -func Uptime() (uint64, error) { - return UptimeWithContext(context.Background()) -} - func UptimeWithContext(ctx context.Context) (uint64, error) { boot, err := BootTime() if err != nil { return 0, err } - return uptime(boot), nil -} - -func Users() ([]UserStat, error) { - return UsersWithContext(context.Background()) + return timeSince(boot), nil } func UsersWithContext(ctx context.Context) ([]UserStat, error) { @@ -236,12 +174,7 @@ func getLSB() (*LSB, error) { return ret, nil } -func PlatformInformation() (platform string, family string, version string, err error) { - return PlatformInformationWithContext(context.Background()) -} - func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) { - lsb, err := getLSB() if err != nil { lsb = &LSB{} @@ -370,10 +303,6 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil } -func KernelVersion() (version string, err error) { - return KernelVersionWithContext(context.Background()) -} - func KernelVersionWithContext(ctx context.Context) (version string, err error) { var utsname unix.Utsname err = unix.Uname(&utsname) @@ -432,18 +361,10 @@ func getSusePlatform(contents []string) string { return "suse" } -func Virtualization() (string, string, error) { - return VirtualizationWithContext(context.Background()) -} - func VirtualizationWithContext(ctx context.Context) (string, string, error) { return common.VirtualizationWithContext(ctx) } -func SensorsTemperatures() ([]TemperatureStat, error) { - return SensorsTemperaturesWithContext(context.Background()) -} - func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { var temperatures []TemperatureStat files, err := filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*")) diff --git a/host/host_openbsd.go b/host/host_openbsd.go index 03e00cf..cfac1e9 100644 --- a/host/host_openbsd.go +++ b/host/host_openbsd.go @@ -8,7 +8,6 @@ import ( "encoding/binary" "io/ioutil" "os" - "runtime" "strings" "unsafe" @@ -23,54 +22,16 @@ const ( UTHostSize = 16 ) -func Info() (*InfoStat, error) { - return InfoWithContext(context.Background()) +func HostIDWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError } -func InfoWithContext(ctx context.Context) (*InfoStat, error) { - ret := &InfoStat{ - OS: runtime.GOOS, - PlatformFamily: "openbsd", - } - - hostname, err := os.Hostname() - if err == nil { - ret.Hostname = hostname - } - - kernelArch, err := kernelArch() - if err == nil { - ret.KernelArch = kernelArch - } - - platform, family, version, err := PlatformInformation() - if err == nil { - ret.Platform = platform - ret.PlatformFamily = family - ret.PlatformVersion = version - } - system, role, err := Virtualization() - if err == nil { - ret.VirtualizationSystem = system - ret.VirtualizationRole = role - } - - procs, err := process.Pids() - if err == nil { - ret.Procs = uint64(len(procs)) - } - - boot, err := BootTime() - if err == nil { - ret.BootTime = boot - ret.Uptime = uptime(boot) +func numProcs(ctx context.Context) (uint64, error) { + procs, err := process.PidsWithContext(ctx) + if err != nil { + return 0, err } - - return ret, nil -} - -func PlatformInformation() (string, string, string, error) { - return PlatformInformationWithContext(context.Background()) + return uint64(len(procs)), nil } func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { @@ -90,18 +51,10 @@ func PlatformInformationWithContext(ctx context.Context) (string, string, string return platform, family, version, nil } -func Virtualization() (string, string, error) { - return VirtualizationWithContext(context.Background()) -} - func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } -func Users() ([]UserStat, error) { - return UsersWithContext(context.Background()) -} - func UsersWithContext(ctx context.Context) ([]UserStat, error) { var ret []UserStat utmpfile := "/var/run/utmp" @@ -141,19 +94,11 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) { return ret, nil } -func SensorsTemperatures() ([]TemperatureStat, error) { - return SensorsTemperaturesWithContext(context.Background()) -} - func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } -func KernelVersion() (string, error) { - return KernelVersionWithContext(context.Background()) -} - func KernelVersionWithContext(ctx context.Context) (string, error) { - _, _, version, err := PlatformInformation() + _, _, version, err := PlatformInformationWithContext(ctx) return version, err } diff --git a/host/host_posix.go b/host/host_posix.go index a1b2479..1cdf16d 100644 --- a/host/host_posix.go +++ b/host/host_posix.go @@ -8,7 +8,7 @@ import ( "golang.org/x/sys/unix" ) -func kernelArch() (string, error) { +func KernelArch() (string, error) { var utsname unix.Utsname err := unix.Uname(&utsname) return string(utsname.Machine[:bytes.IndexByte(utsname.Machine[:], 0)]), err diff --git a/host/host_solaris.go b/host/host_solaris.go index c6061b8..9180db5 100644 --- a/host/host_solaris.go +++ b/host/host_solaris.go @@ -9,86 +9,19 @@ import ( "os" "os/exec" "regexp" - "runtime" "strconv" "strings" - "time" "github.com/shirou/gopsutil/internal/common" ) -func Info() (*InfoStat, error) { - return InfoWithContext(context.Background()) -} - -func InfoWithContext(ctx context.Context) (*InfoStat, error) { - result := &InfoStat{ - OS: runtime.GOOS, - } - - hostname, err := os.Hostname() - if err != nil { - return nil, err - } - result.Hostname = hostname - - // Parse versions from output of `uname(1)` - uname, err := exec.LookPath("uname") - if err != nil { - return nil, err - } - - out, err := invoke.CommandWithContext(ctx, uname, "-srv") - if err != nil { - return nil, err - } - - fields := strings.Fields(string(out)) - if len(fields) >= 1 { - result.PlatformFamily = fields[0] - } - if len(fields) >= 2 { - result.KernelVersion = fields[1] - } - if len(fields) == 3 { - result.PlatformVersion = fields[2] - } - - kernelArch, err := kernelArch() - if err == nil { - result.KernelArch = kernelArch - } - - // Find distribution name from /etc/release - fh, err := os.Open("/etc/release") +func HostIDWithContext(ctx context.Context) (string, error) { + platform, err := parseReleaseFile() if err != nil { - return nil, err - } - defer fh.Close() - - sc := bufio.NewScanner(fh) - if sc.Scan() { - line := strings.TrimSpace(sc.Text()) - switch { - case strings.HasPrefix(line, "SmartOS"): - result.Platform = "SmartOS" - case strings.HasPrefix(line, "OpenIndiana"): - result.Platform = "OpenIndiana" - case strings.HasPrefix(line, "OmniOS"): - result.Platform = "OmniOS" - case strings.HasPrefix(line, "Open Storage"): - result.Platform = "NexentaStor" - case strings.HasPrefix(line, "Solaris"): - result.Platform = "Solaris" - case strings.HasPrefix(line, "Oracle Solaris"): - result.Platform = "Solaris" - default: - result.Platform = strings.Fields(line)[0] - } + return "", err } - switch result.Platform { - case "SmartOS": + if platform == "SmartOS" { // If everything works, use the current zone ID as the HostID if present. zonename, err := exec.LookPath("zonename") if err == nil { @@ -102,59 +35,45 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { if line == "global" { hostname, err := os.Hostname() if err == nil { - result.HostID = hostname + return hostname, nil } } else { - result.HostID = strings.TrimSpace(line) - break + return strings.TrimSpace(line), nil } } } } } - // If HostID is still empty, use hostid(1), which can lie to callers but at + // If HostID is still unknown, use hostid(1), which can lie to callers but at // this point there are no hardware facilities available. This behavior // matches that of other supported OSes. - if result.HostID == "" { - hostID, err := exec.LookPath("hostid") + hostID, err := exec.LookPath("hostid") + if err == nil { + out, err := invoke.CommandWithContext(ctx, hostID) if err == nil { - out, err := invoke.CommandWithContext(ctx, hostID) - if err == nil { - sc := bufio.NewScanner(bytes.NewReader(out)) - for sc.Scan() { - line := sc.Text() - result.HostID = strings.TrimSpace(line) - break - } + sc := bufio.NewScanner(bytes.NewReader(out)) + for sc.Scan() { + line := sc.Text() + return strings.TrimSpace(line), nil } } } - // Find the boot time and calculate uptime relative to it - bootTime, err := BootTime() - if err != nil { - return nil, err - } - result.BootTime = bootTime - result.Uptime = uptimeSince(bootTime) + return "", nil +} - // Count number of processes based on the number of entries in /proc +// Count number of processes based on the number of entries in /proc +func numProcs(ctx context.Context) (uint64, error) { dirs, err := ioutil.ReadDir("/proc") if err != nil { - return nil, err + return 0, err } - result.Procs = uint64(len(dirs)) - - return result, nil + return uint64(len(dirs)), nil } var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`) -func BootTime() (uint64, error) { - return BootTimeWithContext(context.Background()) -} - func BootTimeWithContext(ctx context.Context) (uint64, error) { kstat, err := exec.LookPath("kstat") if err != nil { @@ -174,80 +93,92 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) { return strconv.ParseUint(kstats[0][2], 10, 64) } -func Uptime() (uint64, error) { - return UptimeWithContext(context.Background()) -} - func UptimeWithContext(ctx context.Context) (uint64, error) { bootTime, err := BootTime() if err != nil { return 0, err } - return uptimeSince(bootTime), nil -} - -func uptimeSince(since uint64) uint64 { - return uint64(time.Now().Unix()) - since -} - -func Users() ([]UserStat, error) { - return UsersWithContext(context.Background()) + return timeSince(bootTime), nil } func UsersWithContext(ctx context.Context) ([]UserStat, error) { return []UserStat{}, common.ErrNotImplementedError } -func SensorsTemperatures() ([]TemperatureStat, error) { - return SensorsTemperaturesWithContext(context.Background()) -} - func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } -func Virtualization() (string, string, error) { - return VirtualizationWithContext(context.Background()) -} - func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } -func KernelVersion() (string, error) { - return KernelVersionWithContext(context.Background()) +// Find distribution name from /etc/release +func parseReleaseFile() (string, error) { + b, err := ioutil.ReadFile("/etc/release") + if err != nil { + return "", err + } + s := string(b) + s = strings.TrimSpace(s) + + var platform string + + switch { + case strings.HasPrefix(s, "SmartOS"): + platform = "SmartOS" + case strings.HasPrefix(s, "OpenIndiana"): + platform = "OpenIndiana" + case strings.HasPrefix(s, "OmniOS"): + platform = "OmniOS" + case strings.HasPrefix(s, "Open Storage"): + platform = "NexentaStor" + case strings.HasPrefix(s, "Solaris"): + platform = "Solaris" + case strings.HasPrefix(s, "Oracle Solaris"): + platform = "Solaris" + default: + platform = strings.Fields(s)[0] + } + + return platform, nil } -func KernelVersionWithContext(ctx context.Context) (string, error) { - // Parse versions from output of `uname(1)` +// parseUnameOutput returns platformFamily, kernelVersion and platformVersion +func parseUnameOutput(ctx context.Context) (string, string, string, error) { uname, err := exec.LookPath("uname") if err != nil { - return "", err + return "", "", "", err } out, err := invoke.CommandWithContext(ctx, uname, "-srv") if err != nil { - return "", err + return "", "", "", err } fields := strings.Fields(string(out)) - if len(fields) >= 2 { - return fields[1], nil + if len(fields) < 3 { + return "", "", "", fmt.Errorf("malformed `uname` output") } - return "", fmt.Errorf("could not get kernel version") + + return fields[0], fields[1], fields[2], nil } -func PlatformInformation() (platform string, family string, version string, err error) { - return PlatformInformationWithContext(context.Background()) +func KernelVersionWithContext(ctx context.Context) (string, error) { + _, kernelVersion, _, err := parseUnameOutput(ctx) + return kernelVersion, err } -func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) { - /* This is not finished yet at all. Please contribute! */ +func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { + platform, err := parseReleaseFile() + if err != nil { + return "", "", "", err + } - version, err = KernelVersion() + platformFamily, _, platformVersion, err := parseUnameOutput(ctx) if err != nil { return "", "", "", err } - return "solaris", "solaris", version, nil + return platform, platformFamily, platformVersion, nil } diff --git a/host/host_windows.go b/host/host_windows.go index e73c8c8..6d45458 100644 --- a/host/host_windows.go +++ b/host/host_windows.go @@ -6,8 +6,6 @@ import ( "context" "fmt" "math" - "os" - "runtime" "strings" "sync/atomic" "syscall" @@ -16,7 +14,7 @@ import ( "github.com/StackExchange/wmi" "github.com/shirou/gopsutil/internal/common" - process "github.com/shirou/gopsutil/process" + "github.com/shirou/gopsutil/process" "golang.org/x/sys/windows" ) @@ -64,66 +62,7 @@ type msAcpi_ThermalZoneTemperature struct { InstanceName string } -func Info() (*InfoStat, error) { - return InfoWithContext(context.Background()) -} - -func InfoWithContext(ctx context.Context) (*InfoStat, error) { - ret := &InfoStat{ - OS: runtime.GOOS, - } - - { - hostname, err := os.Hostname() - if err == nil { - ret.Hostname = hostname - } - } - - { - platform, family, version, err := PlatformInformationWithContext(ctx) - if err == nil { - ret.Platform = platform - ret.PlatformFamily = family - ret.PlatformVersion = version - } else { - return ret, err - } - } - - { - kernelArch, err := kernelArch() - if err == nil { - ret.KernelArch = kernelArch - } - } - - { - boot, err := BootTimeWithContext(ctx) - if err == nil { - ret.BootTime = boot - ret.Uptime, _ = Uptime() - } - } - - { - hostID, err := getMachineGuid() - if err == nil { - ret.HostID = hostID - } - } - - { - procs, err := process.PidsWithContext(ctx) - if err == nil { - ret.Procs = uint64(len(procs)) - } - } - - return ret, nil -} - -func getMachineGuid() (string, error) { +func HostIDWithContext(ctx context.Context) (string, error) { // there has been reports of issues on 32bit using golang.org/x/sys/windows/registry, see https://github.com/shirou/gopsutil/pull/312#issuecomment-277422612 // for rationale of using windows.RegOpenKeyEx/RegQueryValueEx instead of registry.OpenKey/GetStringValue var h windows.Handle @@ -153,8 +92,12 @@ func getMachineGuid() (string, error) { return strings.ToLower(hostID), nil } -func Uptime() (uint64, error) { - return UptimeWithContext(context.Background()) +func numProcs(ctx context.Context) (uint64, error) { + procs, err := process.PidsWithContext(ctx) + if err != nil { + return 0, err + } + return uint64(len(procs)), nil } func UptimeWithContext(ctx context.Context) (uint64, error) { @@ -170,17 +113,9 @@ func UptimeWithContext(ctx context.Context) (uint64, error) { return uint64((time.Duration(r1) * time.Millisecond).Seconds()), nil } -func bootTimeFromUptime(up uint64) uint64 { - return uint64(time.Now().Unix()) - up -} - // cachedBootTime must be accessed via atomic.Load/StoreUint64 var cachedBootTime uint64 -func BootTime() (uint64, error) { - return BootTimeWithContext(context.Background()) -} - func BootTimeWithContext(ctx context.Context) (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { @@ -190,15 +125,11 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) { if err != nil { return 0, err } - t = bootTimeFromUptime(up) + t = timeSince(up) atomic.StoreUint64(&cachedBootTime, t) return t, nil } -func PlatformInformation() (platform string, family string, version string, err error) { - return PlatformInformationWithContext(context.Background()) -} - func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) { // GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest // RtlGetVersion bypasses this lying layer and returns the true Windows version @@ -212,7 +143,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil } // Platform - var h windows.Handle // like getMachineGuid(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx + var h windows.Handle // like HostIDWithContext(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx err = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Windows NT\CurrentVersion`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h) if err != nil { return @@ -258,20 +189,12 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil return platform, family, version, nil } -func Users() ([]UserStat, error) { - return UsersWithContext(context.Background()) -} - func UsersWithContext(ctx context.Context) ([]UserStat, error) { var ret []UserStat return ret, common.ErrNotImplementedError } -func SensorsTemperatures() ([]TemperatureStat, error) { - return SensorsTemperaturesWithContext(context.Background()) -} - func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { var ret []TemperatureStat var dst []msAcpi_ThermalZoneTemperature @@ -299,24 +222,16 @@ func kelvinToCelsius(temp uint32, n int) float64 { return math.Trunc((t+0.5/n10)*n10) / n10 } -func Virtualization() (string, string, error) { - return VirtualizationWithContext(context.Background()) -} - func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } -func KernelVersion() (string, error) { - return KernelVersionWithContext(context.Background()) -} - func KernelVersionWithContext(ctx context.Context) (string, error) { - _, _, version, err := PlatformInformation() + _, _, version, err := PlatformInformationWithContext(ctx) return version, err } -func kernelArch() (string, error) { +func KernelArch() (string, error) { var systemInfo systemInfo procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo)))