diff --git a/host/host.go b/host/host.go index 1a6545b99..548e92e82 100644 --- a/host/host.go +++ b/host/host.go @@ -25,7 +25,7 @@ type InfoStat struct { PlatformVersion string `json:"platformVersion"` VirtualizationSystem string `json:"virtualizationSystem"` VirtualizationRole string `json:"virtualizationRole"` // guest or host - + HostID string `json:"hostid"` // ex: uuid } type UserStat struct { diff --git a/host/host_darwin.go b/host/host_darwin.go index 199ea61e5..43c49b2d1 100644 --- a/host/host_darwin.go +++ b/host/host_darwin.go @@ -56,6 +56,11 @@ func Info() (*InfoStat, error) { ret.Procs = uint64(len(procs)) } + values, err := common.DoSysctrl("kern.uuid") + if err == nil && len(values) == 1 && values[0] != "" { + ret.HostID = values[0] + } + return ret, nil } diff --git a/host/host_freebsd.go b/host/host_freebsd.go index 2159ae874..58a06c298 100644 --- a/host/host_freebsd.go +++ b/host/host_freebsd.go @@ -59,6 +59,11 @@ func Info() (*InfoStat, error) { ret.Procs = uint64(len(procs)) } + values, err := common.DoSysctrl("kern.hostuuid") + if err == nil && len(values) == 1 && values[0] != "" { + ret.HostID = values[0] + } + return ret, nil } diff --git a/host/host_linux.go b/host/host_linux.go index 3d73242d1..838609cec 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -61,6 +61,22 @@ func Info() (*InfoStat, error) { ret.Procs = numProcs } + sysProductUUID := common.HostSys("class/dmi/id/product_uuid") + switch { + case common.PathExists(sysProductUUID): + lines, err := common.ReadLines(sysProductUUID) + if err == nil && len(lines) > 0 && lines[0] != "" { + ret.HostID = lines[0] + break + } + fallthrough + default: + values, err := common.DoSysctrl("kernel.random.boot_id") + if err == nil && len(values) == 1 && values[0] != "" { + ret.HostID = values[0] + } + } + return ret, nil } diff --git a/host/host_test.go b/host/host_test.go index d73d1879f..18832abf3 100644 --- a/host/host_test.go +++ b/host/host_test.go @@ -66,8 +66,9 @@ func TestHostInfoStat_String(t *testing.T) { OS: "linux", Platform: "ubuntu", BootTime: 1447040000, + HostID: "edfd25ff-3c9c-b1a4-e660-bd826495ad35", } - e := `{"hostname":"test","uptime":3000,"bootTime":1447040000,"procs":100,"os":"linux","platform":"ubuntu","platformFamily":"","platformVersion":"","virtualizationSystem":"","virtualizationRole":""}` + e := `{"hostname":"test","uptime":3000,"bootTime":1447040000,"procs":100,"os":"linux","platform":"ubuntu","platformFamily":"","platformVersion":"","virtualizationSystem":"","virtualizationRole":"","hostid":"edfd25ff-3c9c-b1a4-e660-bd826495ad35"}` if e != fmt.Sprintf("%v", v) { t.Errorf("HostInfoStat string is invalid: %v", v) } diff --git a/internal/common/common.go b/internal/common/common.go index 42cbaf92a..f0ea6dd36 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -26,7 +26,7 @@ import ( var ( Timeout = 3 * time.Second - TimeoutErr = errors.New("Command timed out.") + ErrTimeout = errors.New("Command timed out.") ) type Invoker interface { @@ -338,6 +338,6 @@ func WaitTimeout(c *exec.Cmd, timeout time.Duration) error { } // wait for the command to return after killing it <-done - return TimeoutErr + return ErrTimeout } } diff --git a/internal/common/common_linux.go b/internal/common/common_linux.go index 06fe4cbb1..9568106fb 100644 --- a/internal/common/common_linux.go +++ b/internal/common/common_linux.go @@ -2,7 +2,31 @@ package common -import "os" +import ( + "os" + "os/exec" + "strings" +) + +func DoSysctrl(mib string) ([]string, error) { + err := os.Setenv("LC_ALL", "C") + if err != nil { + return []string{}, err + } + sysctl, err := exec.LookPath("/sbin/sysctl") + if err != nil { + return []string{}, err + } + out, err := exec.Command(sysctl, "-n", mib).Output() + if err != nil { + return []string{}, err + } + v := strings.Replace(string(out), "{ ", "", 1) + v = strings.Replace(string(v), " }", "", 1) + values := strings.Fields(string(v)) + + return values, nil +} func NumProcs() (uint64, error) { f, err := os.Open(HostProc())