mirror of https://github.com/shirou/gopsutil
Merge pull request #331 from jen20/solaris-host
Host: Add Solaris support for Info(), BootTime(), Uptime()pull/335/head
commit
4fb1a667c4
@ -0,0 +1,132 @@
|
|||||||
|
package host
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/internal/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Info() (*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("/usr/bin/uname")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := invoke.Command(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]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find distribution name from /etc/release
|
||||||
|
fh, err := os.Open("/etc/release")
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// Count number of processes based on the number of entries in /proc
|
||||||
|
dirs, err := ioutil.ReadDir("/proc")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.Procs = uint64(len(dirs))
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
|
||||||
|
|
||||||
|
func BootTime() (uint64, error) {
|
||||||
|
kstat, err := exec.LookPath("/usr/bin/kstat")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := invoke.Command(kstat, "-p", "unix:0:system_misc:boot_time")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
kstats := kstatMatch.FindAllStringSubmatch(string(out), -1)
|
||||||
|
if len(kstats) != 1 {
|
||||||
|
return 0, fmt.Errorf("Expected 1 kstat, found %d", len(kstats))
|
||||||
|
}
|
||||||
|
|
||||||
|
return strconv.ParseUint(kstats[0][2], 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uptime() (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 []UserStat{}, common.ErrNotImplementedError
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package mem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/shirou/gopsutil/internal/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VirtualMemory for Solaris is a minimal implementation which only returns
|
||||||
|
// what Nomad needs. It does take into account global vs zone, however.
|
||||||
|
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||||
|
result := &VirtualMemoryStat{}
|
||||||
|
|
||||||
|
zoneName, err := zoneName()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if zoneName == "global" {
|
||||||
|
cap, err := globalZoneMemoryCapacity()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.Total = cap
|
||||||
|
} else {
|
||||||
|
cap, err := nonGlobalZoneMemoryCapacity()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result.Total = cap
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SwapMemory() (*SwapMemoryStat, error) {
|
||||||
|
return nil, common.ErrNotImplementedError
|
||||||
|
}
|
||||||
|
|
||||||
|
func zoneName() (string, error) {
|
||||||
|
zonename, err := exec.LookPath("/usr/bin/zonename")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := invoke.Command(zonename)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(string(out)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var globalZoneMemoryCapacityMatch = regexp.MustCompile(`Memory size: ([\d]+) Megabytes`)
|
||||||
|
|
||||||
|
func globalZoneMemoryCapacity() (uint64, error) {
|
||||||
|
prtconf, err := exec.LookPath("/usr/sbin/prtconf")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := invoke.Command(prtconf)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
match := globalZoneMemoryCapacityMatch.FindAllStringSubmatch(string(out), -1)
|
||||||
|
if len(match) != 1 {
|
||||||
|
return 0, errors.New("Memory size not contained in output of /usr/sbin/prtconf")
|
||||||
|
}
|
||||||
|
|
||||||
|
totalMB, err := strconv.ParseUint(match[0][1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalMB * 1024 * 1024, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
|
||||||
|
|
||||||
|
func nonGlobalZoneMemoryCapacity() (uint64, error) {
|
||||||
|
kstat, err := exec.LookPath("/usr/bin/kstat")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := invoke.Command(kstat, "-p", "-c", "zone_memory_cap", "memory_cap:*:*:physcap")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
kstats := kstatMatch.FindAllStringSubmatch(string(out), -1)
|
||||||
|
if len(kstats) != 1 {
|
||||||
|
return 0, fmt.Errorf("Expected 1 kstat, found %d", len(kstats))
|
||||||
|
}
|
||||||
|
|
||||||
|
memSizeBytes, err := strconv.ParseUint(kstats[0][2], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return memSizeBytes, nil
|
||||||
|
}
|
Loading…
Reference in New Issue