From 92fb51026aa2b884b0def65a76431ce0143ec150 Mon Sep 17 00:00:00 2001 From: Cameron Sparr Date: Tue, 10 Nov 2015 14:59:01 -0700 Subject: [PATCH] Godep update: gopsutil --- Godeps/Godeps.json | 39 +- .../src/github.com/shirou/gopsutil/.gitignore | 4 + .../src/github.com/shirou/gopsutil/LICENSE | 27 ++ .../src/github.com/shirou/gopsutil/README.rst | 270 ++++++++++++ .../shirou/gopsutil/common/common.go | 218 ++++++++++ .../shirou/gopsutil/common/common_darwin.go | 60 +++ .../shirou/gopsutil/common/common_freebsd.go | 61 +++ .../shirou/gopsutil/common/common_linux.go | 3 + .../shirou/gopsutil/common/common_test.go | 90 ++++ .../shirou/gopsutil/common/common_unix.go | 40 ++ .../shirou/gopsutil/common/common_windows.go | 110 +++++ .../github.com/shirou/gopsutil/coverall.sh | 26 ++ .../shirou/gopsutil/cpu/cpu_darwin.go | 100 ----- .../shirou/gopsutil/cpu/cpu_darwin_cgo.go | 107 +++++ .../shirou/gopsutil/cpu/cpu_darwin_nocgo.go | 14 + .../shirou/gopsutil/cpu/cpu_linux.go | 4 +- .../shirou/gopsutil/disk/disk_linux.go | 2 +- .../src/github.com/shirou/gopsutil/doc.go | 1 + .../github.com/shirou/gopsutil/host/host.go | 37 ++ .../shirou/gopsutil/host/host_darwin.go | 137 ++++++ .../shirou/gopsutil/host/host_darwin_amd64.go | 19 + .../shirou/gopsutil/host/host_freebsd.go | 183 ++++++++ .../gopsutil/host/host_freebsd_amd64.go | 41 ++ .../shirou/gopsutil/host/host_linux.go | 406 ++++++++++++++++++ .../shirou/gopsutil/host/host_linux_386.go | 44 ++ .../shirou/gopsutil/host/host_linux_amd64.go | 42 ++ .../shirou/gopsutil/host/host_linux_arm.go | 42 ++ .../shirou/gopsutil/host/host_linux_test.go | 61 +++ .../shirou/gopsutil/host/host_test.go | 67 +++ .../shirou/gopsutil/host/host_windows.go | 122 ++++++ .../shirou/gopsutil/host/types_darwin.go | 17 + .../shirou/gopsutil/host/types_freebsd.go | 43 ++ .../shirou/gopsutil/host/types_linux.go | 45 ++ .../shirou/gopsutil/load/load_linux.go | 4 +- .../shirou/gopsutil/mem/mem_darwin_test.go | 2 +- .../shirou/gopsutil/mem/mem_linux.go | 5 +- .../src/github.com/shirou/gopsutil/mktypes.sh | 37 ++ .../shirou/gopsutil/net/net_darwin.go | 60 --- .../shirou/gopsutil/net/net_freebsd.go | 6 - .../shirou/gopsutil/net/net_linux.go | 62 +-- .../shirou/gopsutil/net/net_unix.go | 68 +++ .../shirou/gopsutil/process/process_linux.go | 20 +- .../shirou/gopsutil/windows_memo.rst | 36 ++ testutil/testutil.go | 2 +- 44 files changed, 2503 insertions(+), 281 deletions(-) create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/.gitignore create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/LICENSE create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/README.rst create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/common/common.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_darwin.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_freebsd.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_linux.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_test.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_unix.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_windows.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/coverall.sh create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_cgo.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_nocgo.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/doc.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin_amd64.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd_amd64.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_386.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_amd64.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_arm.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_test.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_test.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_windows.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_darwin.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_freebsd.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_linux.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/mktypes.sh create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_unix.go create mode 100644 Godeps/_workspace/src/github.com/shirou/gopsutil/windows_memo.rst diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 7ef120069..70924b5df 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,9 +1,6 @@ { "ImportPath": "github.com/influxdb/telegraf", "GoVersion": "go1.5.1", - "Packages": [ - "./..." - ], "Deps": [ { "ImportPath": "bitbucket.org/ww/goautoneg", @@ -172,39 +169,9 @@ "Rev": "5bb5cfc093ad18a28148c578f8632cfdb4d802e4" }, { - "ImportPath": "github.com/shirou/gopsutil/cpu", - "Comment": "1.0.0-161-g3303647", - "Rev": "3303647209557312e5db51450ea8bbdef56d5176" - }, - { - "ImportPath": "github.com/shirou/gopsutil/disk", - "Comment": "1.0.0-161-g3303647", - "Rev": "3303647209557312e5db51450ea8bbdef56d5176" - }, - { - "ImportPath": "github.com/shirou/gopsutil/docker", - "Comment": "1.0.0-161-g3303647", - "Rev": "3303647209557312e5db51450ea8bbdef56d5176" - }, - { - "ImportPath": "github.com/shirou/gopsutil/load", - "Comment": "1.0.0-161-g3303647", - "Rev": "3303647209557312e5db51450ea8bbdef56d5176" - }, - { - "ImportPath": "github.com/shirou/gopsutil/mem", - "Comment": "1.0.0-161-g3303647", - "Rev": "3303647209557312e5db51450ea8bbdef56d5176" - }, - { - "ImportPath": "github.com/shirou/gopsutil/net", - "Comment": "1.0.0-161-g3303647", - "Rev": "3303647209557312e5db51450ea8bbdef56d5176" - }, - { - "ImportPath": "github.com/shirou/gopsutil/process", - "Comment": "1.0.0-161-g3303647", - "Rev": "3303647209557312e5db51450ea8bbdef56d5176" + "ImportPath": "github.com/shirou/gopsutil", + "Comment": "1.0.0-173-g1e9aabb", + "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617" }, { "ImportPath": "github.com/streadway/amqp", diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/.gitignore b/Godeps/_workspace/src/github.com/shirou/gopsutil/.gitignore new file mode 100644 index 000000000..194eab896 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/.gitignore @@ -0,0 +1,4 @@ +*~ +#* +_obj +*.tmp \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/LICENSE b/Godeps/_workspace/src/github.com/shirou/gopsutil/LICENSE new file mode 100644 index 000000000..602b2c098 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/LICENSE @@ -0,0 +1,27 @@ +gopsutil is distributed under BSD license reproduced below. + +Copyright (c) 2014, WAKAYAMA Shirou +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the gopsutil authors nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/README.rst b/Godeps/_workspace/src/github.com/shirou/gopsutil/README.rst new file mode 100644 index 000000000..a858ff09e --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/README.rst @@ -0,0 +1,270 @@ +gopsutil: psutil for golang +============================== + +.. image:: https://drone.io/github.com/shirou/gopsutil/status.png + :target: https://drone.io/github.com/shirou/gopsutil + +.. image:: https://coveralls.io/repos/shirou/gopsutil/badge.png?branch=master + :target: https://coveralls.io/r/shirou/gopsutil?branch=master + + +This is a port of psutil (http://pythonhosted.org/psutil/). The challenge is porting all +psutil functions on some architectures... + +.. highlights:: Package Structure Changed! + + Package (a.k.a. directory) structure has been changed!! see `issue 24 `_ + +.. highlights:: golang 1.4 will become REQUIRED! + + Since syscall package becomes frozen, we should use golang/x/sys of golang 1.4 as soon as possible. + + +Available Architectures +------------------------------------ + +- FreeBSD i386/amd64 +- Linux i386/amd64/arm(raspberry pi) +- Windows/amd64 +- Darwin/amd64 + +All works are implemented without cgo by porting c struct to golang struct. + + +Usage +--------- + +.. code:: go + + import ( + "fmt" + + "github.com/shirou/gopsutil/mem" + ) + + func main() { + v, _ := mem.VirtualMemory() + + // almost every return value is a struct + fmt.Printf("Total: %v, Free:%v, UsedPercent:%f%%\n", v.Total, v.Free, v.UsedPercent) + + // convert to JSON. String() is also implemented + fmt.Println(v) + } + +The output is below. + +:: + + Total: 3179569152, Free:284233728, UsedPercent:84.508194% + {"total":3179569152,"available":492572672,"used":2895335424,"usedPercent":84.50819439828305, (snip)} + +You can set an alternative location to /proc by setting the HOST_PROC environment variable. + +Documentation +------------------------ + +see http://godoc.org/github.com/shirou/gopsutil + + +More Info +-------------------- + +Several methods have been added which are not present in psutil, but will provide useful information. + +- host/HostInfo() (linux) + + - Hostname + - Uptime + - Procs + - OS (ex: "linux") + - Platform (ex: "ubuntu", "arch") + - PlatformFamily (ex: "debian") + - PlatformVersion (ex: "Ubuntu 13.10") + - VirtualizationSystem (ex: "LXC") + - VirtualizationRole (ex: "guest"/"host") + +- cpu/CPUInfo() (linux, freebsd) + + - CPU (ex: 0, 1, ...) + - VendorID (ex: "GenuineIntel") + - Family + - Model + - Stepping + - PhysicalID + - CoreID + - Cores (ex: 2) + - ModelName (ex: "Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz") + - Mhz + - CacheSize + - Flags (ex: "fpu vme de pse tsc msr pae mce cx8 ...") + +- load/LoadAvg() (linux, freebsd) + + - Load1 + - Load5 + - Load15 + +- docker/GetDockerIDList() (linux only) + + - container id list ([]string) + +- docker/CgroupCPU() (linux only) + + - user + - system + +- docker/CgroupMem() (linux only) + + - various status + +Some codes are ported from Ohai. many thanks. + + +Current Status +------------------ + +- x: work +- b: almost work but something broken + +================= ====== ======= ====== ======= +name Linux FreeBSD MacOSX Windows +cpu_times x x x x +cpu_count x x x x +cpu_percent x x x x +cpu_times_percent x x x x +virtual_memory x x x x +swap_memory x x x +disk_partitions x x x x +disk_io_counters x x +disk_usage x x x x +net_io_counters x x b x +boot_time x x x x +users x x x x +pids x x x x +pid_exists x x x x +net_connections x x +net_if_addrs +net_if_stats +================= ====== ======= ====== ======= + +Process class +^^^^^^^^^^^^^^^ + +================ ===== ======= ====== ======= +name Linux FreeBSD MacOSX Windows +pid x x x x +ppid x x x x +name x x x x +cmdline x x x +create_time x +status x x x +cwd x +exe x x x +uids x x x +gids x x x +terminal x x x +io_counters x +nice x x x +num_fds x +num_ctx_switches x +num_threads x x x x +cpu_times x +memory_info x x x +memory_info_ex x +memory_maps x +open_files x +send_signal x x x +suspend x x x +resume x x x +terminate x x x +kill x x x +username x +ionice +rlimit +num_handlres +threads +cpu_percent x x +cpu_affinity +memory_percent +parent x x +children +connections x x +is_running +================ ===== ======= ====== ======= + +Original Metrics +^^^^^^^^^^^^^^^^^^^ +================== ===== ======= ====== ======= +item Linux FreeBSD MacOSX Windows +**HostInfo** +hostname x x x x + uptime x x x + proces x x + os x x x x + platform x x x + platformfamiliy x x x + virtualization x +**CPU** + VendorID x x x x + Family x x x x + Model x x x x + Stepping x x x x + PhysicalID x + CoreID x + Cores x x + ModelName x x x x +**LoadAvg** + Load1 x x x + Load5 x x x + Load15 x x x +**GetDockerID** + container id x no no no +**CgroupsCPU** + user x no no no + system x no no no +**CgroupsMem** + various x no no no +================== ===== ======= ====== ======= + +- future work + + - process_iter + - wait_procs + - Process class + + - as_dict + - wait + + +License +------------ + +New BSD License (same as psutil) + + +Related Works +----------------------- + +I have been influenced by the following great works: + +- psutil: http://pythonhosted.org/psutil/ +- dstat: https://github.com/dagwieers/dstat +- gosigar: https://github.com/cloudfoundry/gosigar/ +- goprocinfo: https://github.com/c9s/goprocinfo +- go-ps: https://github.com/mitchellh/go-ps +- ohai: https://github.com/opscode/ohai/ +- bosun: https://github.com/bosun-monitor/bosun/tree/master/cmd/scollector/collectors +- mackerel: https://github.com/mackerelio/mackerel-agent/tree/master/metrics + +How to Contribute +--------------------------- + +1. Fork it +2. Create your feature branch (git checkout -b my-new-feature) +3. Commit your changes (git commit -am 'Add some feature') +4. Push to the branch (git push origin my-new-feature) +5. Create new Pull Request + +My English is terrible, so documentation or correcting comments are also +welcome. diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common.go new file mode 100644 index 000000000..d04cdfd7f --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common.go @@ -0,0 +1,218 @@ +// +// gopsutil is a port of psutil(http://pythonhosted.org/psutil/). +// This covers these architectures. +// - linux (amd64, arm) +// - freebsd (amd64) +// - windows (amd64) +package common + +import ( + "bufio" + "errors" + "io/ioutil" + "net/url" + "os" + "os/exec" + "path" + "reflect" + "runtime" + "strconv" + "strings" +) + +type Invoker interface { + Command(string, ...string) ([]byte, error) +} + +type Invoke struct{} + +func (i Invoke) Command(name string, arg ...string) ([]byte, error) { + return exec.Command(name, arg...).Output() +} + +type FakeInvoke struct { + CommandExpectedDir string // CommandExpectedDir specifies dir which includes expected outputs. + Suffix string // Suffix species expected file name suffix such as "fail" + Error error // If Error specfied, return the error. +} + +// Command in FakeInvoke returns from expected file if exists. +func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) { + if i.Error != nil { + return []byte{}, i.Error + } + + arch := runtime.GOOS + + fname := strings.Join(append([]string{name}, arg...), "") + fname = url.QueryEscape(fname) + var dir string + if i.CommandExpectedDir == "" { + dir = "expected" + } else { + dir = i.CommandExpectedDir + } + fpath := path.Join(dir, arch, fname) + if i.Suffix != "" { + fpath += "_" + i.Suffix + } + if PathExists(fpath) { + return ioutil.ReadFile(fpath) + } else { + return exec.Command(name, arg...).Output() + } +} + +var NotImplementedError = errors.New("not implemented yet") + +// ReadLines reads contents from a file and splits them by new lines. +// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1). +func ReadLines(filename string) ([]string, error) { + return ReadLinesOffsetN(filename, 0, -1) +} + +// ReadLines reads contents from file and splits them by new line. +// The offset tells at which line number to start. +// The count determines the number of lines to read (starting from offset): +// n >= 0: at most n lines +// n < 0: whole file +func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) { + f, err := os.Open(filename) + if err != nil { + return []string{""}, err + } + defer f.Close() + + var ret []string + + r := bufio.NewReader(f) + for i := 0; i < n+int(offset) || n < 0; i++ { + line, err := r.ReadString('\n') + if err != nil { + break + } + if i < int(offset) { + continue + } + ret = append(ret, strings.Trim(line, "\n")) + } + + return ret, nil +} + +func IntToString(orig []int8) string { + ret := make([]byte, len(orig)) + size := -1 + for i, o := range orig { + if o == 0 { + size = i + break + } + ret[i] = byte(o) + } + if size == -1 { + size = len(orig) + } + + return string(ret[0:size]) +} + +func ByteToString(orig []byte) string { + n := -1 + l := -1 + for i, b := range orig { + // skip left side null + if l == -1 && b == 0 { + continue + } + if l == -1 { + l = i + } + + if b == 0 { + break + } + n = i + 1 + } + if n == -1 { + return string(orig) + } + return string(orig[l:n]) +} + +// Parse to int32 without error +func mustParseInt32(val string) int32 { + vv, _ := strconv.ParseInt(val, 10, 32) + return int32(vv) +} + +// Parse to uint64 without error +func mustParseUint64(val string) uint64 { + vv, _ := strconv.ParseInt(val, 10, 64) + return uint64(vv) +} + +// Parse to Float64 without error +func mustParseFloat64(val string) float64 { + vv, _ := strconv.ParseFloat(val, 64) + return vv +} + +// StringsHas checks the target string slice containes src or not +func StringsHas(target []string, src string) bool { + for _, t := range target { + if strings.TrimSpace(t) == src { + return true + } + } + return false +} + +// StringsContains checks the src in any string of the target string slice +func StringsContains(target []string, src string) bool { + for _, t := range target { + if strings.Contains(t, src) { + return true + } + } + return false +} + +// get struct attributes. +// This method is used only for debugging platform dependent code. +func attributes(m interface{}) map[string]reflect.Type { + typ := reflect.TypeOf(m) + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + + attrs := make(map[string]reflect.Type) + if typ.Kind() != reflect.Struct { + return nil + } + + for i := 0; i < typ.NumField(); i++ { + p := typ.Field(i) + if !p.Anonymous { + attrs[p.Name] = p.Type + } + } + + return attrs +} + +func PathExists(filename string) bool { + if _, err := os.Stat(filename); err == nil { + return true + } + return false +} + +//GetEnv retreives the environment variable key. If it does not exist it returns the default. +func GetEnv(key string, dfault string) string { + value := os.Getenv(key) + if value == "" { + value = dfault + } + return value +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_darwin.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_darwin.go new file mode 100644 index 000000000..7d6f3c692 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_darwin.go @@ -0,0 +1,60 @@ +// +build darwin + +package common + +import ( + "os/exec" + "strings" + "syscall" + "unsafe" +) + +func DoSysctrl(mib string) ([]string, error) { + out, err := exec.Command("/usr/sbin/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 CallSyscall(mib []int32) ([]byte, uint64, error) { + miblen := uint64(len(mib)) + + // get required buffer size + length := uint64(0) + _, _, err := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + 0, + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + var b []byte + return b, length, err + } + if length == 0 { + var b []byte + return b, length, err + } + // get proc info itself + buf := make([]byte, length) + _, _, err = syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + return buf, length, err + } + + return buf, length, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_freebsd.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_freebsd.go new file mode 100644 index 000000000..3c1124655 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_freebsd.go @@ -0,0 +1,61 @@ +// +build freebsd + +package common + +import ( + "syscall" + "os/exec" + "strings" + "unsafe" +) + +func DoSysctrl(mib string) ([]string, error) { + out, err := exec.Command("/sbin/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 CallSyscall(mib []int32) ([]byte, uint64, error) { + miblen := uint64(len(mib)) + + // get required buffer size + length := uint64(0) + _, _, err := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + 0, + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + var b []byte + return b, length, err + } + if length == 0 { + var b []byte + return b, length, err + } + // get proc info itself + buf := make([]byte, length) + _, _, err = syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + return buf, length, err + } + + return buf, length, nil +} + diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_linux.go new file mode 100644 index 000000000..0a122e9d6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_linux.go @@ -0,0 +1,3 @@ +// +build linux + +package common diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_test.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_test.go new file mode 100644 index 000000000..b2660b2af --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_test.go @@ -0,0 +1,90 @@ +package common + +import ( + "fmt" + "strings" + "testing" +) + +func TestReadlines(t *testing.T) { + ret, err := ReadLines("common_test.go") + if err != nil { + t.Error(err) + } + if !strings.Contains(ret[0], "package common") { + t.Error("could not read correctly") + } +} + +func TestReadLinesOffsetN(t *testing.T) { + ret, err := ReadLinesOffsetN("common_test.go", 2, 1) + if err != nil { + t.Error(err) + } + fmt.Println(ret[0]) + if !strings.Contains(ret[0], `import (`) { + t.Error("could not read correctly") + } +} + +func TestIntToString(t *testing.T) { + src := []int8{65, 66, 67} + dst := IntToString(src) + if dst != "ABC" { + t.Error("could not convert") + } +} +func TestByteToString(t *testing.T) { + src := []byte{65, 66, 67} + dst := ByteToString(src) + if dst != "ABC" { + t.Error("could not convert") + } + + src = []byte{0, 65, 66, 67} + dst = ByteToString(src) + if dst != "ABC" { + t.Error("could not convert") + } +} + +func TestmustParseInt32(t *testing.T) { + ret := mustParseInt32("11111") + if ret != int32(11111) { + t.Error("could not parse") + } +} +func TestmustParseUint64(t *testing.T) { + ret := mustParseUint64("11111") + if ret != uint64(11111) { + t.Error("could not parse") + } +} +func TestmustParseFloat64(t *testing.T) { + ret := mustParseFloat64("11111.11") + if ret != float64(11111.11) { + t.Error("could not parse") + } + ret = mustParseFloat64("11111") + if ret != float64(11111) { + t.Error("could not parse") + } +} +func TestStringsContains(t *testing.T) { + target, err := ReadLines("common_test.go") + if err != nil { + t.Error(err) + } + if !StringsContains(target, "func TestStringsContains(t *testing.T) {") { + t.Error("cloud not test correctly") + } +} + +func TestPathExists(t *testing.T) { + if !PathExists("common_test.go") { + t.Error("exists but return not exists") + } + if PathExists("should_not_exists.go") { + t.Error("not exists but return exists") + } +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_unix.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_unix.go new file mode 100644 index 000000000..d0557ad25 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_unix.go @@ -0,0 +1,40 @@ +// +build linux freebsd darwin + +package common + +import ( + "os/exec" + "strconv" + "strings" +) + +func CallLsof(invoke Invoker, pid int32, args ...string) ([]string, error) { + var cmd []string + if pid == 0 { // will get from all processes. + cmd = []string{"-a", "-n", "-P"} + } else { + cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))} + } + cmd = append(cmd, args...) + lsof, err := exec.LookPath("lsof") + if err != nil { + return []string{}, err + } + out, err := invoke.Command(lsof, cmd...) + if err != nil { + // if no pid found, lsof returnes code 1. + if err.Error() == "exit status 1" && len(out) == 0 { + return []string{}, nil + } + } + lines := strings.Split(string(out), "\n") + + var ret []string + for _, l := range lines[1:] { + if len(l) == 0 { + continue + } + ret = append(ret, l) + } + return ret, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_windows.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_windows.go new file mode 100644 index 000000000..d727378cb --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/common/common_windows.go @@ -0,0 +1,110 @@ +// +build windows + +package common + +import ( + "syscall" + "unsafe" +) + +// for double values +type PDH_FMT_COUNTERVALUE_DOUBLE struct { + CStatus uint32 + DoubleValue float64 +} + +// for 64 bit integer values +type PDH_FMT_COUNTERVALUE_LARGE struct { + CStatus uint32 + LargeValue int64 +} + +// for long values +type PDH_FMT_COUNTERVALUE_LONG struct { + CStatus uint32 + LongValue int32 + padding [4]byte +} + +// windows system const +const ( + ERROR_SUCCESS = 0 + ERROR_FILE_NOT_FOUND = 2 + DRIVE_REMOVABLE = 2 + DRIVE_FIXED = 3 + HKEY_LOCAL_MACHINE = 0x80000002 + RRF_RT_REG_SZ = 0x00000002 + RRF_RT_REG_DWORD = 0x00000010 + PDH_FMT_LONG = 0x00000100 + PDH_FMT_DOUBLE = 0x00000200 + PDH_FMT_LARGE = 0x00000400 + PDH_INVALID_DATA = 0xc0000bc6 + PDH_INVALID_HANDLE = 0xC0000bbc + PDH_NO_DATA = 0x800007d5 +) + +var ( + Modkernel32 = syscall.NewLazyDLL("kernel32.dll") + ModNt = syscall.NewLazyDLL("ntdll.dll") + ModPdh = syscall.NewLazyDLL("pdh.dll") + + ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes") + ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation") + PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery") + PdhAddCounter = ModPdh.NewProc("PdhAddCounterW") + PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData") + PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue") + PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery") +) + +type FILETIME struct { + DwLowDateTime uint32 + DwHighDateTime uint32 +} + +// borrowed from net/interface_windows.go +func BytePtrToString(p *uint8) string { + a := (*[10000]uint8)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + +// CounterInfo +// copied from https://github.com/mackerelio/mackerel-agent/ +type CounterInfo struct { + PostName string + CounterName string + Counter syscall.Handle +} + +// CreateQuery XXX +// copied from https://github.com/mackerelio/mackerel-agent/ +func CreateQuery() (syscall.Handle, error) { + var query syscall.Handle + r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query))) + if r != 0 { + return 0, err + } + return query, nil +} + +// CreateCounter XXX +func CreateCounter(query syscall.Handle, pname, cname string) (*CounterInfo, error) { + var counter syscall.Handle + r, _, err := PdhAddCounter.Call( + uintptr(query), + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(cname))), + 0, + uintptr(unsafe.Pointer(&counter))) + if r != 0 { + return nil, err + } + return &CounterInfo{ + PostName: pname, + CounterName: cname, + Counter: counter, + }, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/coverall.sh b/Godeps/_workspace/src/github.com/shirou/gopsutil/coverall.sh new file mode 100644 index 000000000..35aa298ba --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/coverall.sh @@ -0,0 +1,26 @@ +#/bin/sh + +# see http://www.songmu.jp/riji/entry/2015-01-15-goveralls-multi-package.html + +set -e +# cleanup +cleanup() { + if [ $tmpprof != "" ] && [ -f $tmpprof ]; then + rm -f $tmpprof + fi + exit +} +trap cleanup INT QUIT TERM EXIT + +# メインの処理 +prof=${1:-".profile.cov"} +echo "mode: count" > $prof +gopath1=$(echo $GOPATH | cut -d: -f1) +for pkg in $(go list ./...); do + tmpprof=$gopath1/src/$pkg/profile.tmp + go test -covermode=count -coverprofile=$tmpprof $pkg + if [ -f $tmpprof ]; then + cat $tmpprof | tail -n +2 >> $prof + rm $tmpprof + fi +done diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin.go index 455294717..4066b6515 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin.go @@ -2,27 +2,10 @@ package cpu -/* -#include -#include -#include -#include -#include -#include -#include -#include -#include -*/ -import "C" - import ( - "bytes" - "encoding/binary" - "fmt" "os/exec" "strconv" "strings" - "unsafe" ) // sys/resource.h @@ -38,89 +21,6 @@ const ( // default value. from time.h var ClocksPerSec = float64(128) -// these CPU times for darwin is borrowed from influxdb/telegraf. - -func perCPUTimes() ([]CPUTimesStat, error) { - var ( - count C.mach_msg_type_number_t - cpuload *C.processor_cpu_load_info_data_t - ncpu C.natural_t - ) - - status := C.host_processor_info(C.host_t(C.mach_host_self()), - C.PROCESSOR_CPU_LOAD_INFO, - &ncpu, - (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), - &count) - - if status != C.KERN_SUCCESS { - return nil, fmt.Errorf("host_processor_info error=%d", status) - } - - // jump through some cgo casting hoops and ensure we properly free - // the memory that cpuload points to - target := C.vm_map_t(C.mach_task_self_) - address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) - defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) - - // the body of struct processor_cpu_load_info - // aka processor_cpu_load_info_data_t - var cpu_ticks [C.CPU_STATE_MAX]uint32 - - // copy the cpuload array to a []byte buffer - // where we can binary.Read the data - size := int(ncpu) * binary.Size(cpu_ticks) - buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size)) - - bbuf := bytes.NewBuffer(buf) - - var ret []CPUTimesStat - - for i := 0; i < int(ncpu); i++ { - err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks) - if err != nil { - return nil, err - } - - c := CPUTimesStat{ - CPU: fmt.Sprintf("cpu%d", i), - User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, - System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, - Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, - Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, - } - - ret = append(ret, c) - } - - return ret, nil -} - -func allCPUTimes() ([]CPUTimesStat, error) { - var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT - var cpuload C.host_cpu_load_info_data_t - - status := C.host_statistics(C.host_t(C.mach_host_self()), - C.HOST_CPU_LOAD_INFO, - C.host_info_t(unsafe.Pointer(&cpuload)), - &count) - - if status != C.KERN_SUCCESS { - return nil, fmt.Errorf("host_statistics error=%d", status) - } - - c := CPUTimesStat{ - CPU: "cpu-total", - User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, - System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, - Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, - Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, - } - - return []CPUTimesStat{c}, nil - -} - func CPUTimes(percpu bool) ([]CPUTimesStat, error) { if percpu { return perCPUTimes() diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_cgo.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_cgo.go new file mode 100644 index 000000000..29732172a --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_cgo.go @@ -0,0 +1,107 @@ +// +build darwin +// +build cgo + +package cpu + +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +import "C" + +import ( + "bytes" + "encoding/binary" + "fmt" + "unsafe" +) + +// these CPU times for darwin is borrowed from influxdb/telegraf. + +func perCPUTimes() ([]CPUTimesStat, error) { + var ( + count C.mach_msg_type_number_t + cpuload *C.processor_cpu_load_info_data_t + ncpu C.natural_t + ) + + status := C.host_processor_info(C.host_t(C.mach_host_self()), + C.PROCESSOR_CPU_LOAD_INFO, + &ncpu, + (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), + &count) + + if status != C.KERN_SUCCESS { + return nil, fmt.Errorf("host_processor_info error=%d", status) + } + + // jump through some cgo casting hoops and ensure we properly free + // the memory that cpuload points to + target := C.vm_map_t(C.mach_task_self_) + address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) + defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) + + // the body of struct processor_cpu_load_info + // aka processor_cpu_load_info_data_t + var cpu_ticks [C.CPU_STATE_MAX]uint32 + + // copy the cpuload array to a []byte buffer + // where we can binary.Read the data + size := int(ncpu) * binary.Size(cpu_ticks) + buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size)) + + bbuf := bytes.NewBuffer(buf) + + var ret []CPUTimesStat + + for i := 0; i < int(ncpu); i++ { + err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks) + if err != nil { + return nil, err + } + + c := CPUTimesStat{ + CPU: fmt.Sprintf("cpu%d", i), + User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, + System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, + Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, + Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, + } + + ret = append(ret, c) + } + + return ret, nil +} + +func allCPUTimes() ([]CPUTimesStat, error) { + var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT + var cpuload C.host_cpu_load_info_data_t + + status := C.host_statistics(C.host_t(C.mach_host_self()), + C.HOST_CPU_LOAD_INFO, + C.host_info_t(unsafe.Pointer(&cpuload)), + &count) + + if status != C.KERN_SUCCESS { + return nil, fmt.Errorf("host_statistics error=%d", status) + } + + c := CPUTimesStat{ + CPU: "cpu-total", + User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, + System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, + Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, + Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, + } + + return []CPUTimesStat{c}, nil + +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_nocgo.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_nocgo.go new file mode 100644 index 000000000..ca545705c --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_darwin_nocgo.go @@ -0,0 +1,14 @@ +// +build darwin +// +build !cgo + +package cpu + +import "github.com/shirou/gopsutil/common" + +func perCPUTimes() ([]CPUTimesStat, error) { + return []CPUTimesStat{}, common.NotImplementedError +} + +func allCPUTimes() ([]CPUTimesStat, error) { + return []CPUTimesStat{}, common.NotImplementedError +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_linux.go index 942ef0c2a..1bec8a73f 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_linux.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/cpu/cpu_linux.go @@ -25,7 +25,7 @@ func init() { } func CPUTimes(percpu bool) ([]CPUTimesStat, error) { - filename := "/proc/stat" + filename := common.GetEnv("HOST_PROC", "/proc") + "/stat" var lines = []string{} if percpu { var startIdx uint = 1 @@ -56,7 +56,7 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) { } func CPUInfo() ([]CPUInfoStat, error) { - filename := "/proc/cpuinfo" + filename := common.GetEnv("HOST_PROC", "/proc") + "cpuinfo" lines, _ := common.ReadLines(filename) var ret []CPUInfoStat diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_linux.go index df59f6a90..93f59b098 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_linux.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/disk/disk_linux.go @@ -238,7 +238,7 @@ func DiskPartitions(all bool) ([]DiskPartitionStat, error) { } func DiskIOCounters() (map[string]DiskIOCountersStat, error) { - filename := "/proc/diskstats" + filename := common.GetEnv("HOST_PROC", "/proc") + "/diskstats" lines, err := common.ReadLines(filename) if err != nil { return nil, err diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/doc.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/doc.go new file mode 100644 index 000000000..6a65fe268 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/doc.go @@ -0,0 +1 @@ +package gopsutil diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host.go new file mode 100644 index 000000000..523b63461 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host.go @@ -0,0 +1,37 @@ +package host + +import ( + "encoding/json" +) + +// A HostInfoStat describes the host status. +// This is not in the psutil but it useful. +type HostInfoStat struct { + Hostname string `json:"hostname"` + Uptime uint64 `json:"uptime"` + Procs uint64 `json:"procs"` // number of processes + OS string `json:"os"` // ex: freebsd, linux + Platform string `json:"platform"` // ex: ubuntu, linuxmint + PlatformFamily string `json:"platform_family"` // ex: debian, rhel + PlatformVersion string `json:"platform_version"` + VirtualizationSystem string `json:"virtualization_system"` + VirtualizationRole string `json:"virtualization_role"` // guest or host + +} + +type UserStat struct { + User string `json:"user"` + Terminal string `json:"terminal"` + Host string `json:"host"` + Started int `json:"started"` +} + +func (h HostInfoStat) String() string { + s, _ := json.Marshal(h) + return string(s) +} + +func (u UserStat) String() string { + s, _ := json.Marshal(u) + return string(s) +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin.go new file mode 100644 index 000000000..0a0e462c0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin.go @@ -0,0 +1,137 @@ +// +build darwin + +package host + +import ( + "bytes" + "encoding/binary" + "io/ioutil" + "os" + "os/exec" + "runtime" + "strconv" + "strings" + "unsafe" + + common "github.com/shirou/gopsutil/common" +) + +func HostInfo() (*HostInfoStat, error) { + ret := &HostInfoStat{ + OS: runtime.GOOS, + PlatformFamily: "darwin", + } + + hostname, err := os.Hostname() + if err == nil { + ret.Hostname = hostname + } + + platform, family, version, err := GetPlatformInformation() + if err == nil { + ret.Platform = platform + ret.PlatformFamily = family + ret.PlatformVersion = version + } + system, role, err := GetVirtualization() + if err == nil { + ret.VirtualizationSystem = system + ret.VirtualizationRole = role + } + + values, err := common.DoSysctrl("kern.boottime") + if err == nil { + // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 + v := strings.Replace(values[2], ",", "", 1) + t, err := strconv.ParseUint(v, 10, 64) + if err != nil { + ret.Uptime = t + } + } + + return ret, nil +} + +func BootTime() (uint64, error) { + values, err := common.DoSysctrl("kern.boottime") + if err != nil { + return 0, err + } + // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 + v := strings.Replace(values[2], ",", "", 1) + + boottime, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return 0, err + } + + return uint64(boottime), nil +} + +func Users() ([]UserStat, error) { + utmpfile := "/var/run/utmpx" + var ret []UserStat + + file, err := os.Open(utmpfile) + if err != nil { + return ret, err + } + + buf, err := ioutil.ReadAll(file) + if err != nil { + return ret, err + } + + u := Utmpx{} + entrySize := int(unsafe.Sizeof(u)) + count := len(buf) / entrySize + + for i := 0; i < count; i++ { + b := buf[i*entrySize : i*entrySize+entrySize] + + var u Utmpx + br := bytes.NewReader(b) + err := binary.Read(br, binary.LittleEndian, &u) + if err != nil { + continue + } + if u.Type != 7 { // skip if not USERPROCESS + 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 + +} + +func GetPlatformInformation() (string, string, string, error) { + platform := "" + family := "" + version := "" + + out, err := exec.Command("uname", "-s").Output() + if err == nil { + platform = strings.ToLower(strings.TrimSpace(string(out))) + } + + out, err = exec.Command("uname", "-r").Output() + if err == nil { + version = strings.ToLower(strings.TrimSpace(string(out))) + } + + return platform, family, version, nil +} + +func GetVirtualization() (string, string, error) { + system := "" + role := "" + + return system, role, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin_amd64.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin_amd64.go new file mode 100644 index 000000000..3ea52d527 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_darwin_amd64.go @@ -0,0 +1,19 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_darwin.go + +package host + +type Utmpx struct { + User [256]int8 + Id [4]int8 + Line [32]int8 + Pid int32 + Type int16 + Pad_cgo_0 [6]byte + Tv Timeval + Host [256]int8 + Pad [16]uint32 +} +type Timeval struct { + Sec int32 +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd.go new file mode 100644 index 000000000..edff5b7ec --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd.go @@ -0,0 +1,183 @@ +// +build freebsd + +package host + +import ( + "bytes" + "encoding/binary" + "io/ioutil" + "os" + "os/exec" + "runtime" + "strconv" + "strings" + "unsafe" + + common "github.com/shirou/gopsutil/common" +) + +const ( + UTNameSize = 16 /* see MAXLOGNAME in */ + UTLineSize = 8 + UTHostSize = 16 +) + +func HostInfo() (*HostInfoStat, error) { + ret := &HostInfoStat{ + OS: runtime.GOOS, + PlatformFamily: "freebsd", + } + + hostname, err := os.Hostname() + if err == nil { + ret.Hostname = hostname + } + + platform, family, version, err := GetPlatformInformation() + if err == nil { + ret.Platform = platform + ret.PlatformFamily = family + ret.PlatformVersion = version + } + system, role, err := GetVirtualization() + if err == nil { + ret.VirtualizationSystem = system + ret.VirtualizationRole = role + } + + values, err := common.DoSysctrl("kern.boottime") + if err == nil { + // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 + v := strings.Replace(values[2], ",", "", 1) + t, err := strconv.ParseUint(v, 10, 64) + if err == nil { + ret.Uptime = t + } + } + + return ret, nil +} + +func BootTime() (int64, error) { + values, err := common.DoSysctrl("kern.boottime") + if err != nil { + return 0, err + } + // ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014 + v := strings.Replace(values[2], ",", "", 1) + + boottime, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return 0, err + } + + return boottime, nil +} + +func Users() ([]UserStat, error) { + utmpfile := "/var/run/utx.active" + if !common.PathExists(utmpfile) { + utmpfile = "/var/run/utmp" // before 9.0 + return getUsersFromUtmp(utmpfile) + } + + var ret []UserStat + file, err := os.Open(utmpfile) + if err != nil { + return ret, err + } + + buf, err := ioutil.ReadAll(file) + if err != nil { + return ret, err + } + + u := Utmpx{} + entrySize := int(unsafe.Sizeof(u)) - 3 + entrySize = 197 // TODO: why should 197 + count := len(buf) / entrySize + + for i := 0; i < count; i++ { + b := buf[i*entrySize : i*entrySize+entrySize] + var u Utmpx + br := bytes.NewReader(b) + err := binary.Read(br, binary.LittleEndian, &u) + if err != nil || u.Type != 4 { + continue + } + sec := (binary.LittleEndian.Uint32(u.Tv.Sec[:])) / 2 // TODO: + user := UserStat{ + User: common.IntToString(u.User[:]), + Terminal: common.IntToString(u.Line[:]), + Host: common.IntToString(u.Host[:]), + Started: int(sec), + } + + ret = append(ret, user) + } + + return ret, nil + +} + +func GetPlatformInformation() (string, string, string, error) { + platform := "" + family := "" + version := "" + + out, err := exec.Command("uname", "-s").Output() + if err == nil { + platform = strings.ToLower(strings.TrimSpace(string(out))) + } + + out, err = exec.Command("uname", "-r").Output() + if err == nil { + version = strings.ToLower(strings.TrimSpace(string(out))) + } + + return platform, family, version, nil +} + +func GetVirtualization() (string, string, error) { + system := "" + role := "" + + return system, role, nil +} + +// before 9.0 +func getUsersFromUtmp(utmpfile string) ([]UserStat, error) { + var ret []UserStat + file, err := os.Open(utmpfile) + if err != nil { + return ret, err + } + buf, err := ioutil.ReadAll(file) + if err != nil { + return ret, err + } + + u := Utmp{} + entrySize := int(unsafe.Sizeof(u)) + count := len(buf) / entrySize + + for i := 0; i < count; i++ { + b := buf[i*entrySize : i*entrySize+entrySize] + var u Utmp + br := bytes.NewReader(b) + err := binary.Read(br, binary.LittleEndian, &u) + if err != nil || u.Time == 0 { + continue + } + user := UserStat{ + User: common.IntToString(u.Name[:]), + Terminal: common.IntToString(u.Line[:]), + Host: common.IntToString(u.Host[:]), + Started: int(u.Time), + } + + ret = append(ret, user) + } + + return ret, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd_amd64.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd_amd64.go new file mode 100644 index 000000000..46be58688 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_freebsd_amd64.go @@ -0,0 +1,41 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package host + +const ( + sizeofPtr = 0x8 + sizeofShort = 0x2 + sizeofInt = 0x4 + sizeofLong = 0x8 + sizeofLongLong = 0x8 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int64 + _C_long_long int64 +) + +type Utmp struct { + Line [8]int8 + Name [16]int8 + Host [16]int8 + Time int32 +} +type Utmpx struct { + Type int16 + Tv Timeval + Id [8]int8 + Pid int32 + User [32]int8 + Line [16]int8 + Host [125]int8 + // Host [128]int8 + // X__ut_spare [64]int8 +} +type Timeval struct { + Sec [4]byte + Usec [3]byte +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux.go new file mode 100644 index 000000000..9131fa84d --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux.go @@ -0,0 +1,406 @@ +// +build linux + +package host + +import ( + "bytes" + "encoding/binary" + "fmt" + "io/ioutil" + "os" + "os/exec" + "regexp" + "runtime" + "strconv" + "strings" + "unsafe" + + common "github.com/shirou/gopsutil/common" +) + +type LSB struct { + ID string + Release string + Codename string + Description string +} + +func HostInfo() (*HostInfoStat, error) { + ret := &HostInfoStat{ + OS: runtime.GOOS, + } + + hostname, err := os.Hostname() + if err == nil { + ret.Hostname = hostname + } + + platform, family, version, err := GetPlatformInformation() + if err == nil { + ret.Platform = platform + ret.PlatformFamily = family + ret.PlatformVersion = version + } + system, role, err := GetVirtualization() + if err == nil { + ret.VirtualizationSystem = system + ret.VirtualizationRole = role + } + uptime, err := BootTime() + if err == nil { + ret.Uptime = uptime + } + + return ret, nil +} + +// BootTime returns the system boot time expressed in seconds since the epoch. +func BootTime() (uint64, error) { + filename := common.GetEnv("HOST_PROC", "/proc") + "/stat" + lines, err := common.ReadLines(filename) + if err != nil { + return 0, err + } + for _, line := range lines { + if strings.HasPrefix(line, "btime") { + f := strings.Fields(line) + if len(f) != 2 { + return 0, fmt.Errorf("wrong btime format") + } + b, err := strconv.ParseInt(f[1], 10, 64) + if err != nil { + return 0, err + } + return uint64(b), nil + } + } + + return 0, fmt.Errorf("could not find btime") +} + +func Users() ([]UserStat, error) { + utmpfile := "/var/run/utmp" + + file, err := os.Open(utmpfile) + if err != nil { + return nil, err + } + + buf, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + u := utmp{} + entrySize := int(unsafe.Sizeof(u)) + count := len(buf) / entrySize + + ret := make([]UserStat, 0, count) + + for i := 0; i < count; i++ { + b := buf[i*entrySize : i*entrySize+entrySize] + + var u utmp + br := bytes.NewReader(b) + err := binary.Read(br, binary.LittleEndian, &u) + if err != nil { + continue + } + user := UserStat{ + User: common.IntToString(u.User[:]), + Terminal: common.IntToString(u.Line[:]), + Host: common.IntToString(u.Host[:]), + Started: int(u.Tv.TvSec), + } + ret = append(ret, user) + } + + return ret, nil + +} + +func getLSB() (*LSB, error) { + ret := &LSB{} + if common.PathExists("/etc/lsb-release") { + contents, err := common.ReadLines("/etc/lsb-release") + if err != nil { + return ret, err // return empty + } + for _, line := range contents { + field := strings.Split(line, "=") + if len(field) < 2 { + continue + } + switch field[0] { + case "DISTRIB_ID": + ret.ID = field[1] + case "DISTRIB_RELEASE": + ret.Release = field[1] + case "DISTRIB_CODENAME": + ret.Codename = field[1] + case "DISTRIB_DESCRIPTION": + ret.Description = field[1] + } + } + } else if common.PathExists("/usr/bin/lsb_release") { + out, err := exec.Command("/usr/bin/lsb_release").Output() + if err != nil { + return ret, err + } + for _, line := range strings.Split(string(out), "\n") { + field := strings.Split(line, ":") + if len(field) < 2 { + continue + } + switch field[0] { + case "Distributor ID": + ret.ID = field[1] + case "Release": + ret.Release = field[1] + case "Codename": + ret.Codename = field[1] + case "Description": + ret.Description = field[1] + } + } + + } + + return ret, nil +} + +func GetPlatformInformation() (platform string, family string, version string, err error) { + + lsb, err := getLSB() + if err != nil { + lsb = &LSB{} + } + + if common.PathExists("/etc/oracle-release") { + platform = "oracle" + contents, err := common.ReadLines("/etc/oracle-release") + if err == nil { + version = getRedhatishVersion(contents) + } + } else if common.PathExists("/etc/enterprise-release") { + platform = "oracle" + contents, err := common.ReadLines("/etc/enterprise-release") + if err == nil { + version = getRedhatishVersion(contents) + } + } else if common.PathExists("/etc/debian_version") { + if lsb.ID == "Ubuntu" { + platform = "ubuntu" + version = lsb.Release + } else if lsb.ID == "LinuxMint" { + platform = "linuxmint" + version = lsb.Release + } else { + if common.PathExists("/usr/bin/raspi-config") { + platform = "raspbian" + } else { + platform = "debian" + } + contents, err := common.ReadLines("/etc/debian_version") + if err == nil { + version = contents[0] + } + } + } else if common.PathExists("/etc/redhat-release") { + contents, err := common.ReadLines("/etc/redhat-release") + if err == nil { + version = getRedhatishVersion(contents) + platform = getRedhatishPlatform(contents) + } + } else if common.PathExists("/etc/system-release") { + contents, err := common.ReadLines("/etc/system-release") + if err == nil { + version = getRedhatishVersion(contents) + platform = getRedhatishPlatform(contents) + } + } else if common.PathExists("/etc/gentoo-release") { + platform = "gentoo" + contents, err := common.ReadLines("/etc/gentoo-release") + if err == nil { + version = getRedhatishVersion(contents) + } + } else if common.PathExists("/etc/SuSE-release") { + contents, err := common.ReadLines("/etc/SuSE-release") + if err == nil { + version = getSuseVersion(contents) + platform = getSusePlatform(contents) + } + // TODO: slackware detecion + } else if common.PathExists("/etc/arch-release") { + platform = "arch" + // TODO: exherbo detection + } else if lsb.ID == "RedHat" { + platform = "redhat" + version = lsb.Release + } else if lsb.ID == "Amazon" { + platform = "amazon" + version = lsb.Release + } else if lsb.ID == "ScientificSL" { + platform = "scientific" + version = lsb.Release + } else if lsb.ID == "XenServer" { + platform = "xenserver" + version = lsb.Release + } else if lsb.ID != "" { + platform = strings.ToLower(lsb.ID) + version = lsb.Release + } + + switch platform { + case "debian", "ubuntu", "linuxmint", "raspbian": + family = "debian" + case "fedora": + family = "fedora" + case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm": + family = "rhel" + case "suse", "opensuse": + family = "suse" + case "gentoo": + family = "gentoo" + case "slackware": + family = "slackware" + case "arch": + family = "arch" + case "exherbo": + family = "exherbo" + } + + return platform, family, version, nil + +} + +func getRedhatishVersion(contents []string) string { + c := strings.ToLower(strings.Join(contents, "")) + + if strings.Contains(c, "rawhide") { + return "rawhide" + } + if matches := regexp.MustCompile(`release (\d[\d.]*)`).FindStringSubmatch(c); matches != nil { + return matches[1] + } + return "" +} + +func getRedhatishPlatform(contents []string) string { + c := strings.ToLower(strings.Join(contents, "")) + + if strings.Contains(c, "red hat") { + return "redhat" + } + f := strings.Split(c, " ") + + return f[0] +} + +func getSuseVersion(contents []string) string { + version := "" + for _, line := range contents { + if matches := regexp.MustCompile(`VERSION = ([\d.]+)`).FindStringSubmatch(line); matches != nil { + version = matches[1] + } else if matches := regexp.MustCompile(`PATCHLEVEL = ([\d]+)`).FindStringSubmatch(line); matches != nil { + version = version + "." + matches[1] + } + } + return version +} + +func getSusePlatform(contents []string) string { + c := strings.ToLower(strings.Join(contents, "")) + if strings.Contains(c, "opensuse") { + return "opensuse" + } + return "suse" +} + +func GetVirtualization() (string, string, error) { + var system string + var role string + + filename := common.GetEnv("HOST_PROC", "/proc") + "/xen" + if common.PathExists(filename) { + system = "xen" + role = "guest" // assume guest + + if common.PathExists(filename + "/capabilities") { + contents, err := common.ReadLines(filename + "/capabilities") + if err == nil { + if common.StringsHas(contents, "control_d") { + role = "host" + } + } + } + } + + filename = common.GetEnv("HOST_PROC", "/proc") + "/modules" + if common.PathExists(filename) { + contents, err := common.ReadLines(filename) + if err == nil { + if common.StringsContains(contents, "kvm") { + system = "kvm" + role = "host" + } else if common.StringsContains(contents, "vboxdrv") { + system = "vbox" + role = "host" + } else if common.StringsContains(contents, "vboxguest") { + system = "vbox" + role = "guest" + } + } + } + + filename = common.GetEnv("HOST_PROC", "/proc") + "/cpuinfo" + if common.PathExists(filename) { + contents, err := common.ReadLines(filename) + if err == nil { + if common.StringsHas(contents, "QEMU Virtual CPU") || + common.StringsHas(contents, "Common KVM processor") || + common.StringsHas(contents, "Common 32-bit KVM processor") { + system = "kvm" + role = "guest" + } + } + } + + filename = common.GetEnv("HOST_PROC", "/proc") + if common.PathExists(filename + "/bc/0") { + system = "openvz" + role = "host" + } else if common.PathExists(filename + "/vz") { + system = "openvz" + role = "guest" + } + + // not use dmidecode because it requires root + if common.PathExists(filename + "/self/status") { + contents, err := common.ReadLines(filename + "/self/status") + if err == nil { + + if common.StringsHas(contents, "s_context:") || + common.StringsHas(contents, "VxID:") { + system = "linux-vserver" + } + // TODO: guest or host + } + } + + if common.PathExists(filename + "/self/cgroup") { + contents, err := common.ReadLines(filename + "/self/cgroup") + if err == nil { + if common.StringsHas(contents, "lxc") || + common.StringsHas(contents, "docker") { + system = "lxc" + role = "guest" + } else if common.PathExists("/usr/bin/lxc-version") { // TODO: which + system = "lxc" + role = "host" + } + } + } + + return system, role, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_386.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_386.go new file mode 100644 index 000000000..d8f31c2f6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_386.go @@ -0,0 +1,44 @@ +// ATTENTION - FILE MANUAL FIXED AFTER CGO. +// Fixed line: Tv _Ctype_struct_timeval -> Tv UtTv +// Created by cgo -godefs, MANUAL FIXED +// cgo -godefs types_linux.go + +package host + +const ( + sizeofPtr = 0x4 + sizeofShort = 0x2 + sizeofInt = 0x4 + sizeofLong = 0x4 + sizeofLongLong = 0x8 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int32 + _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 UtTv + Addr_v6 [4]int32 + X__unused [20]int8 +} +type exit_status struct { + Termination int16 + Exit int16 +} +type UtTv struct { + TvSec int32 + TvUsec int32 +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_amd64.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_amd64.go new file mode 100644 index 000000000..b04fc17e3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_amd64.go @@ -0,0 +1,42 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_linux.go + +package host + +const ( + sizeofPtr = 0x8 + sizeofShort = 0x2 + sizeofInt = 0x4 + sizeofLong = 0x8 + sizeofLongLong = 0x8 +) + +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 UtTv + Addr_v6 [4]int32 + X__glibc_reserved [20]int8 +} +type exit_status struct { + Termination int16 + Exit int16 +} +type UtTv struct { + TvSec int32 + TvUsec int32 +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_arm.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_arm.go new file mode 100644 index 000000000..329e530f7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_arm.go @@ -0,0 +1,42 @@ +// +build linux +// +build arm + +package host + +const ( + sizeofPtr = 0x8 + sizeofShort = 0x2 + sizeofInt = 0x4 + sizeofLong = 0x8 + sizeofLongLong = 0x8 +) + +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 UtTv + Addr_v6 [4]int32 + X__glibc_reserved [20]int8 +} +type exit_status struct { + Termination int16 + Exit int16 +} +type UtTv struct { + TvSec int32 + TvUsec int32 +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_test.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_test.go new file mode 100644 index 000000000..7808eee3d --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_linux_test.go @@ -0,0 +1,61 @@ +// +build linux + +package host + +import ( + "testing" +) + +func TestGetRedhatishVersion(t *testing.T) { + var ret string + c := []string{"Rawhide"} + ret = getRedhatishVersion(c) + if ret != "rawhide" { + t.Errorf("Could not get version rawhide: %v", ret) + } + + c = []string{"Fedora release 15 (Lovelock)"} + ret = getRedhatishVersion(c) + if ret != "15" { + t.Errorf("Could not get version fedora: %v", ret) + } + + c = []string{"Enterprise Linux Server release 5.5 (Carthage)"} + ret = getRedhatishVersion(c) + if ret != "5.5" { + t.Errorf("Could not get version redhat enterprise: %v", ret) + } + + c = []string{""} + ret = getRedhatishVersion(c) + if ret != "" { + t.Errorf("Could not get version with no value: %v", ret) + } +} + +func TestGetRedhatishPlatform(t *testing.T) { + var ret string + c := []string{"red hat"} + ret = getRedhatishPlatform(c) + if ret != "redhat" { + t.Errorf("Could not get platform redhat: %v", ret) + } + + c = []string{"Fedora release 15 (Lovelock)"} + ret = getRedhatishPlatform(c) + if ret != "fedora" { + t.Errorf("Could not get platform fedora: %v", ret) + } + + c = []string{"Enterprise Linux Server release 5.5 (Carthage)"} + ret = getRedhatishPlatform(c) + if ret != "enterprise" { + t.Errorf("Could not get platform redhat enterprise: %v", ret) + } + + c = []string{""} + ret = getRedhatishPlatform(c) + if ret != "" { + t.Errorf("Could not get platform with no value: %v", ret) + } +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_test.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_test.go new file mode 100644 index 000000000..eb6982904 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_test.go @@ -0,0 +1,67 @@ +package host + +import ( + "fmt" + "testing" +) + +func TestHostInfo(t *testing.T) { + v, err := HostInfo() + if err != nil { + t.Errorf("error %v", err) + } + empty := &HostInfoStat{} + if v == empty { + t.Errorf("Could not get hostinfo %v", v) + } +} + +func TestBoot_time(t *testing.T) { + v, err := BootTime() + if err != nil { + t.Errorf("error %v", err) + } + if v == 0 { + t.Errorf("Could not get boot time %v", v) + } +} + +func TestUsers(t *testing.T) { + v, err := Users() + if err != nil { + t.Errorf("error %v", err) + } + empty := UserStat{} + for _, u := range v { + if u == empty { + t.Errorf("Could not Users %v", v) + } + } +} + +func TestHostInfoStat_String(t *testing.T) { + v := HostInfoStat{ + Hostname: "test", + Uptime: 3000, + Procs: 100, + OS: "linux", + Platform: "ubuntu", + } + e := `{"hostname":"test","uptime":3000,"procs":100,"os":"linux","platform":"ubuntu","platform_family":"","platform_version":"","virtualization_system":"","virtualization_role":""}` + if e != fmt.Sprintf("%v", v) { + t.Errorf("HostInfoStat string is invalid: %v", v) + } +} + +func TestUserStat_String(t *testing.T) { + v := UserStat{ + User: "user", + Terminal: "term", + Host: "host", + Started: 100, + } + e := `{"user":"user","terminal":"term","host":"host","started":100}` + if e != fmt.Sprintf("%v", v) { + t.Errorf("UserStat string is invalid: %v", v) + } +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_windows.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_windows.go new file mode 100644 index 000000000..e8ba125d9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/host_windows.go @@ -0,0 +1,122 @@ +// +build windows + +package host + +import ( + "fmt" + "os" + "runtime" + "strings" + "time" + + "github.com/StackExchange/wmi" + + common "github.com/shirou/gopsutil/common" + process "github.com/shirou/gopsutil/common/process" +) + +var ( + procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime") + osInfo *Win32_OperatingSystem +) + +type Win32_OperatingSystem struct { + Version string + Caption string + ProductType uint32 + BuildNumber string + LastBootUpTime time.Time +} + +func HostInfo() (*HostInfoStat, error) { + ret := &HostInfoStat{ + OS: runtime.GOOS, + } + + hostname, err := os.Hostname() + if err == nil { + ret.Hostname = hostname + } + + platform, family, version, err := GetPlatformInformation() + if err == nil { + ret.Platform = platform + ret.PlatformFamily = family + ret.PlatformVersion = version + } else { + return ret, err + } + + ret.Uptime, err = BootTime() + if err != nil { + return ret, err + } + + procs, err := process.Pids() + if err != nil { + return ret, err + } + + ret.Procs = uint64(len(procs)) + + return ret, nil +} + +func GetOSInfo() (Win32_OperatingSystem, error) { + var dst []Win32_OperatingSystem + q := wmi.CreateQuery(&dst, "") + err := wmi.Query(q, &dst) + if err != nil { + return Win32_OperatingSystem{}, err + } + + osInfo = &dst[0] + + return dst[0], nil +} + +func BootTime() (uint64, error) { + if osInfo == nil { + _, err := GetOSInfo() + if err != nil { + return 0, err + } + } + now := time.Now() + t := osInfo.LastBootUpTime.Local() + return uint64(now.Sub(t).Seconds()), nil +} + +func GetPlatformInformation() (platform string, family string, version string, err error) { + if osInfo == nil { + _, err = GetOSInfo() + if err != nil { + return + } + } + + // Platform + platform = strings.Trim(osInfo.Caption, " ") + + // PlatformFamily + switch osInfo.ProductType { + case 1: + family = "Standalone Workstation" + case 2: + family = "Server (Domain Controller)" + case 3: + family = "Server" + } + + // Platform Version + version = fmt.Sprintf("%s Build %s", osInfo.Version, osInfo.BuildNumber) + + return +} + +func Users() ([]UserStat, error) { + + var ret []UserStat + + return ret, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_darwin.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_darwin.go new file mode 100644 index 000000000..b85822788 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_darwin.go @@ -0,0 +1,17 @@ +// +build ignore +// plus hand editing about timeval + +/* +Input to cgo -godefs. +*/ + +package host + +/* +#include +#include +*/ +import "C" + +type Utmpx C.struct_utmpx +type Timeval C.struct_timeval diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_freebsd.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_freebsd.go new file mode 100644 index 000000000..113b22eea --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_freebsd.go @@ -0,0 +1,43 @@ +// +build ignore + +/* +Input to cgo -godefs. +*/ + +package host + +/* +#define KERNEL +#include +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +*/ +import "C" + +// Machine characteristics; for internal use. + +const ( + sizeofPtr = C.sizeofPtr + sizeofShort = C.sizeof_short + sizeofInt = C.sizeof_int + sizeofLong = C.sizeof_long + sizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +type Utmp C.struct_utmp +type Utmpx C.struct_utmpx +type Timeval C.struct_timeval diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_linux.go new file mode 100644 index 000000000..928545515 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/host/types_linux.go @@ -0,0 +1,45 @@ +// +build ignore + +/* +Input to cgo -godefs. +*/ + +package host + +/* +#define KERNEL +#include +#include + +enum { + sizeofPtr = sizeof(void*), +}; + +*/ +import "C" + +// Machine characteristics; for internal use. + +const ( + sizeofPtr = C.sizeofPtr + sizeofShort = C.sizeof_short + sizeofInt = C.sizeof_int + sizeofLong = C.sizeof_long + sizeofLongLong = C.sizeof_longlong +) + +// Basic types + +type ( + _C_short C.short + _C_int C.int + _C_long C.long + _C_long_long C.longlong +) + +type utmp C.struct_utmp +type exit_status C.struct_exit_status +type UtTv struct { + TvSec int32 + TvUsec int32 +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_linux.go index 6c9926b3b..4ab5a9686 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_linux.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/load/load_linux.go @@ -6,10 +6,12 @@ import ( "io/ioutil" "strconv" "strings" + + common "github.com/shirou/gopsutil/common" ) func LoadAvg() (*LoadAvgStat, error) { - filename := "/proc/loadavg" + filename := common.GetEnv("HOST_PROC", "/proc") + "/loadavg" line, err := ioutil.ReadFile(filename) if err != nil { return nil, err diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_darwin_test.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_darwin_test.go index c52e7d43e..730dc52f3 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_darwin_test.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_darwin_test.go @@ -61,7 +61,7 @@ func TestParseVmStat(t *testing.T) { } if ret.Cached != uint64(128967*4096+449242.*4096) { - t.Errorf("Cached pages, actual: %d, expected: %d", ret.Cached, + t.Errorf("Cached pages, actual: %d, expected: %f", ret.Cached, 128967*4096+449242.*4096) } } diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_linux.go index ccad5da90..e45a0842d 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_linux.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/mem/mem_linux.go @@ -11,7 +11,7 @@ import ( ) func VirtualMemory() (*VirtualMemoryStat, error) { - filename := "/proc/meminfo" + filename := common.GetEnv("HOST_PROC", "/proc") + "/meminfo" lines, _ := common.ReadLines(filename) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+) memavail := false @@ -74,7 +74,8 @@ func SwapMemory() (*SwapMemoryStat, error) { } else { ret.UsedPercent = 0 } - lines, _ := common.ReadLines("/proc/vmstat") + filename := common.GetEnv("HOST_PROC", "/proc") + "/vmstat" + lines, _ := common.ReadLines(filename) for _, l := range lines { fields := strings.Fields(l) if len(fields) < 2 { diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/mktypes.sh b/Godeps/_workspace/src/github.com/shirou/gopsutil/mktypes.sh new file mode 100644 index 000000000..7bf2e2412 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/mktypes.sh @@ -0,0 +1,37 @@ + +DIRS="cpu disk docker host load mem net process" + +GOOS=`uname | tr '[:upper:]' '[:lower:]'` +ARCH=`uname -m` + +case $ARCH in + amd64) + GOARCH="amd64" + ;; + x86_64) + GOARCH="amd64" + ;; + i386) + GOARCH="386" + ;; + i686) + GOARCH="386" + ;; + arm) + GOARCH="arm" + ;; + *) + echo "unknown arch: $ARCH" + exit 1 +esac + +for DIR in $DIRS +do + if [ -e ${DIR}/types_${GOOS}.go ]; then + echo "// +build $GOOS" > ${DIR}/${DIR}_${GOOS}_${GOARCH}.go + echo "// +build $GOARCH" >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go + go tool cgo -godefs ${DIR}/types_${GOOS}.go >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go + fi +done + + diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_darwin.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_darwin.go index bcf2915fa..65c21f882 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_darwin.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_darwin.go @@ -90,63 +90,3 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { return ret, nil } - -// Return a list of network connections opened. -func NetConnections(kind string) ([]NetConnectionStat, error) { - return NetConnectionsPid(kind, 0) -} - -// Return a list of network connections opened by a process. -func NetConnectionsPid(kind string, pid int32) ([]NetConnectionStat, error) { - var ret []NetConnectionStat - - args := []string{"-i"} - switch strings.ToLower(kind) { - default: - fallthrough - case "": - fallthrough - case "all": - fallthrough - case "inet": - args = append(args, "tcp") - case "inet4": - args = append(args, "4") - case "inet6": - args = append(args, "6") - case "tcp": - args = append(args, "tcp") - case "tcp4": - args = append(args, "4tcp") - case "tcp6": - args = append(args, "6tcp") - case "udp": - args = append(args, "udp") - case "udp4": - args = append(args, "6udp") - case "udp6": - args = append(args, "6udp") - case "unix": - return ret, common.NotImplementedError - } - - // we can not use -F filter to get all of required information at once. - r, err := common.CallLsof(invoke, pid, args...) - if err != nil { - return nil, err - } - for _, rr := range r { - if strings.HasPrefix(rr, "COMMAND") { - continue - } - n, err := parseNetLine(rr) - if err != nil { - // fmt.Println(err) // TODO: should debug print? - continue - } - - ret = append(ret, n) - } - - return ret, nil -} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_freebsd.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_freebsd.go index 7cc93a5cd..703d3219d 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_freebsd.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_freebsd.go @@ -81,9 +81,3 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { return ret, nil } - -func NetConnections(kind string) ([]NetConnectionStat, error) { - var ret []NetConnectionStat - - return ret, common.NotImplementedError -} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_linux.go index 6e542449f..73b2bee6c 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_linux.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_linux.go @@ -15,7 +15,7 @@ import ( // every network interface installed on the system is returned // separately. func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { - filename := "/proc/net/dev" + filename := common.GetEnv("HOST_PROC", "/proc") + "/net/dev" lines, err := common.ReadLines(filename) if err != nil { return nil, err @@ -89,63 +89,3 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) { return ret, nil } - -// Return a list of network connections opened. -func NetConnections(kind string) ([]NetConnectionStat, error) { - return NetConnectionsPid(kind, 0) -} - -// Return a list of network connections opened by a process. -func NetConnectionsPid(kind string, pid int32) ([]NetConnectionStat, error) { - var ret []NetConnectionStat - - args := []string{"-i"} - switch strings.ToLower(kind) { - default: - fallthrough - case "": - fallthrough - case "all": - fallthrough - case "inet": - args = append(args, "tcp") - case "inet4": - args = append(args, "4") - case "inet6": - args = append(args, "6") - case "tcp": - args = append(args, "tcp") - case "tcp4": - args = append(args, "4tcp") - case "tcp6": - args = append(args, "6tcp") - case "udp": - args = append(args, "udp") - case "udp4": - args = append(args, "6udp") - case "udp6": - args = append(args, "6udp") - case "unix": - return ret, common.NotImplementedError - } - - // we can not use -F filter to get all of required information at once. - r, err := common.CallLsof(invoke, pid, args...) - if err != nil { - return nil, err - } - for _, rr := range r { - if strings.HasPrefix(rr, "COMMAND") { - continue - } - n, err := parseNetLine(rr) - if err != nil { - // fmt.Println(err) // TODO: should debug print? - continue - } - - ret = append(ret, n) - } - - return ret, nil -} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_unix.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_unix.go new file mode 100644 index 000000000..0b8a844e7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/net/net_unix.go @@ -0,0 +1,68 @@ +// +build linux freebsd darwin + +package net + +import ( + "strings" + + "github.com/shirou/gopsutil/common" +) + +// Return a list of network connections opened. +func NetConnections(kind string) ([]NetConnectionStat, error) { + return NetConnectionsPid(kind, 0) +} + +// Return a list of network connections opened by a process. +func NetConnectionsPid(kind string, pid int32) ([]NetConnectionStat, error) { + var ret []NetConnectionStat + + args := []string{"-i"} + switch strings.ToLower(kind) { + default: + fallthrough + case "": + fallthrough + case "all": + fallthrough + case "inet": + args = append(args, "tcp", "-i", "udp") + case "inet4": + args = append(args, "4") + case "inet6": + args = append(args, "6") + case "tcp": + args = append(args, "tcp") + case "tcp4": + args = append(args, "4tcp") + case "tcp6": + args = append(args, "6tcp") + case "udp": + args = append(args, "udp") + case "udp4": + args = append(args, "6udp") + case "udp6": + args = append(args, "6udp") + case "unix": + return ret, common.NotImplementedError + } + + r, err := common.CallLsof(invoke, pid, args...) + if err != nil { + return nil, err + } + for _, rr := range r { + if strings.HasPrefix(rr, "COMMAND") { + continue + } + n, err := parseNetLine(rr) + if err != nil { + + continue + } + + ret = append(ret, n) + } + + return ret, nil +} diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/process/process_linux.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/process/process_linux.go index 692329fc0..0d3a3973e 100644 --- a/Godeps/_workspace/src/github.com/shirou/gopsutil/process/process_linux.go +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/process/process_linux.go @@ -222,7 +222,7 @@ func (p *Process) IsRunning() (bool, error) { func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { pid := p.Pid var ret []MemoryMapsStat - smapsPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "smaps") + smapsPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "smaps") contents, err := ioutil.ReadFile(smapsPath) if err != nil { return nil, err @@ -303,7 +303,7 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { // Get num_fds from /proc/(pid)/fd func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { pid := p.Pid - statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "fd") + statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "fd") d, err := os.Open(statPath) if err != nil { return 0, nil, err @@ -336,7 +336,7 @@ func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { // Get cwd from /proc/(pid)/cwd func (p *Process) fillFromCwd() (string, error) { pid := p.Pid - cwdPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "cwd") + cwdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cwd") cwd, err := os.Readlink(cwdPath) if err != nil { return "", err @@ -347,7 +347,7 @@ func (p *Process) fillFromCwd() (string, error) { // Get exe from /proc/(pid)/exe func (p *Process) fillFromExe() (string, error) { pid := p.Pid - exePath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "exe") + exePath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "exe") exe, err := os.Readlink(exePath) if err != nil { return "", err @@ -358,7 +358,7 @@ func (p *Process) fillFromExe() (string, error) { // Get cmdline from /proc/(pid)/cmdline func (p *Process) fillFromCmdline() (string, error) { pid := p.Pid - cmdPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "cmdline") + cmdPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "cmdline") cmdline, err := ioutil.ReadFile(cmdPath) if err != nil { return "", err @@ -376,7 +376,7 @@ func (p *Process) fillFromCmdline() (string, error) { // Get IO status from /proc/(pid)/io func (p *Process) fillFromIO() (*IOCountersStat, error) { pid := p.Pid - ioPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "io") + ioPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "io") ioline, err := ioutil.ReadFile(ioPath) if err != nil { return nil, err @@ -415,7 +415,7 @@ func (p *Process) fillFromIO() (*IOCountersStat, error) { // Get memory info from /proc/(pid)/statm func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { pid := p.Pid - memPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "statm") + memPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "statm") contents, err := ioutil.ReadFile(memPath) if err != nil { return nil, nil, err @@ -467,7 +467,7 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { // Get various status from /proc/(pid)/status func (p *Process) fillFromStatus() error { pid := p.Pid - statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "status") + statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "status") contents, err := ioutil.ReadFile(statPath) if err != nil { return err @@ -554,7 +554,7 @@ func (p *Process) fillFromStatus() error { func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32, error) { pid := p.Pid - statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "stat") + statPath := filepath.Join(common.GetEnv("HOST_PROC", "/proc"), strconv.Itoa(int(pid)), "stat") contents, err := ioutil.ReadFile(statPath) if err != nil { return "", 0, nil, 0, 0, err @@ -610,7 +610,7 @@ func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32 func Pids() ([]int32, error) { var ret []int32 - d, err := os.Open("/proc") + d, err := os.Open(common.GetEnv("HOST_PROC", "/proc")) if err != nil { return nil, err } diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/windows_memo.rst b/Godeps/_workspace/src/github.com/shirou/gopsutil/windows_memo.rst new file mode 100644 index 000000000..38abed819 --- /dev/null +++ b/Godeps/_workspace/src/github.com/shirou/gopsutil/windows_memo.rst @@ -0,0 +1,36 @@ +Windows memo +===================== + +Size +---------- + +DWORD + 32-bit unsigned integer +DWORDLONG + 64-bit unsigned integer +DWORD_PTR + unsigned long type for pointer precision +DWORD32 + 32-bit unsigned integer +DWORD64 + 64-bit unsigned integer +HALF_PTR + _WIN64 = int, else short +INT + 32-bit signed integer +INT_PTR + _WIN64 = __int64 else int +LONG + 32-bit signed integer +LONGLONG + 64-bit signed integer +LONG_PTR + _WIN64 = __int64 else long +SHORT + 16-bit integer +SIZE_T + maximum number of bytes to which a pointer can point. typedef ULONG_PTR SIZE_T; +SSIZE_T + signed version of SIZE_T. typedef LONG_PTR SSIZE_T; +WORD + 16-bit unsigned integer \ No newline at end of file diff --git a/testutil/testutil.go b/testutil/testutil.go index 70b3a53a2..92509f9b9 100644 --- a/testutil/testutil.go +++ b/testutil/testutil.go @@ -39,7 +39,7 @@ func MockBatchPoints() client.BatchPoints { // Create a point and add to batch tags := map[string]string{"tag1": "value1"} fields := map[string]interface{}{"value": 1.0} - pt := client.NewPoint("test_point", tags, fields) + pt, _ := client.NewPoint("test_point", tags, fields) bp.AddPoint(pt) return bp