Merge pull request #331 from jen20/solaris-host

Host: Add Solaris support for Info(), BootTime(), Uptime()
pull/335/head
shirou 8 years ago committed by GitHub
commit 4fb1a667c4

@ -174,13 +174,13 @@ Current Status
- x: work
- b: almost works, but something is broken
=================== ====== ======= ======= ====== =======
name Linux FreeBSD OpenBSD MacOSX Windows
=================== ====== ======= ======= ====== ======= =======
name Linux FreeBSD OpenBSD MacOSX Windows Solaris
cpu_times x x x x x
cpu_count x x x x x
cpu_percent x x x x x
cpu_times_percent x x x x x
virtual_memory x x x x x
virtual_memory x x x x x b
swap_memory x x x x
disk_partitions x x x x x
disk_io_counters x x x
@ -248,12 +248,12 @@ Original Metrics
================== ===== ======= ======= ====== ======= =======
item Linux FreeBSD OpenBSD MacOSX Windows Solaris
**HostInfo**
hostname x x x x x
uptime x x x x
proces x x x
os x x x x x
platform x x x x
platformfamily x x x x
hostname x x x x x x
uptime x x x x x
proces x x x x
os x x x x x x
platform x x x x x
platformfamily x x x x x
virtualization x
**CPU**
VendorID x x x x x x

@ -1,4 +1,4 @@
// +build !darwin,!linux,!freebsd,!openbsd,!windows
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows
package host

@ -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
}

@ -1,4 +1,4 @@
// +build !darwin,!linux,!freebsd,!openbsd,!windows
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows
package mem

@ -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
}

@ -2,12 +2,17 @@ package mem
import (
"fmt"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
)
func TestVirtual_memory(t *testing.T) {
if runtime.GOOS == "solaris" {
t.Skip("Only .Total is supported on Solaris")
}
v, err := VirtualMemory()
if err != nil {
t.Errorf("error %v", err)

Loading…
Cancel
Save