Merge branch 'master' into f-gopsutil
This commit is contained in:
commit
b9ea658cce
|
@ -8,6 +8,8 @@ IMPROVEMENTS:
|
||||||
|
|
||||||
BUG FIXES:
|
BUG FIXES:
|
||||||
|
|
||||||
|
* dns: Fixed an issue where SRV lookups for services on a node registered with non-IP addresses were missing the CNAME record in the additional section of the response. [GH-2695]
|
||||||
|
|
||||||
## 0.7.3 (January 26, 2017)
|
## 0.7.3 (January 26, 2017)
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
|
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
"github.com/hashicorp/serf/coordinate"
|
"github.com/hashicorp/serf/coordinate"
|
||||||
"github.com/hashicorp/serf/serf"
|
"github.com/hashicorp/serf/serf"
|
||||||
"github.com/shirou/gopsutil/host"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -594,45 +593,7 @@ func (a *Agent) setupClient() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeRandomID will generate a random UUID for a node.
|
// setupNodeID will pull the persisted node ID, if any, or create a random one
|
||||||
func (a *Agent) makeRandomID() (string, error) {
|
|
||||||
id, err := uuid.GenerateUUID()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
a.logger.Printf("[DEBUG] Using random ID %q as node ID", id)
|
|
||||||
return id, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// makeNodeID will try to find a host-specific ID, or else will generate a
|
|
||||||
// random ID. The returned ID will always be formatted as a GUID. We don't
|
|
||||||
// tell the caller whether this ID is random or stable since the consequences
|
|
||||||
// are high for us if this changes, so we will persist it either way. This will
|
|
||||||
// let gopsutil change implementations without affecting in-place upgrades of
|
|
||||||
// nodes.
|
|
||||||
func (a *Agent) makeNodeID() (string, error) {
|
|
||||||
// Try to get a stable ID associated with the host itself.
|
|
||||||
info, err := host.Info()
|
|
||||||
if err != nil {
|
|
||||||
a.logger.Printf("[DEBUG] Couldn't get a unique ID from the host: %v", err)
|
|
||||||
return a.makeRandomID()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the host ID parses as a UUID, since we don't have complete
|
|
||||||
// control over this process.
|
|
||||||
id := strings.ToLower(info.HostID)
|
|
||||||
if _, err := uuid.ParseUUID(id); err != nil {
|
|
||||||
a.logger.Printf("[DEBUG] Unique ID %q from host isn't formatted as a UUID: %v",
|
|
||||||
id, err)
|
|
||||||
return a.makeRandomID()
|
|
||||||
}
|
|
||||||
|
|
||||||
a.logger.Printf("[DEBUG] Using unique ID %q from host as node ID", id)
|
|
||||||
return id, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupNodeID will pull the persisted node ID, if any, or create one
|
|
||||||
// and persist it.
|
// and persist it.
|
||||||
func (a *Agent) setupNodeID(config *Config) error {
|
func (a *Agent) setupNodeID(config *Config) error {
|
||||||
// If they've configured a node ID manually then just use that, as
|
// If they've configured a node ID manually then just use that, as
|
||||||
|
@ -645,14 +606,15 @@ func (a *Agent) setupNodeID(config *Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// For dev mode we have no filesystem access so just make one.
|
// For dev mode we have no filesystem access so just make a GUID.
|
||||||
if a.config.DevMode {
|
if a.config.DevMode {
|
||||||
id, err := a.makeNodeID()
|
id, err := uuid.GenerateUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config.NodeID = types.NodeID(id)
|
config.NodeID = types.NodeID(id)
|
||||||
|
a.logger.Printf("[INFO] agent: Generated unique node ID %q for this agent (will not be persisted in dev mode)", config.NodeID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,7 +637,7 @@ func (a *Agent) setupNodeID(config *Config) error {
|
||||||
|
|
||||||
// If we still don't have a valid node ID, make one.
|
// If we still don't have a valid node ID, make one.
|
||||||
if config.NodeID == "" {
|
if config.NodeID == "" {
|
||||||
id, err := a.makeNodeID()
|
id, err := uuid.GenerateUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -687,6 +649,7 @@ func (a *Agent) setupNodeID(config *Config) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
config.NodeID = types.NodeID(id)
|
config.NodeID = types.NodeID(id)
|
||||||
|
a.logger.Printf("[INFO] agent: Generated unique node ID %q for this agent (persisted)", config.NodeID)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -876,8 +876,7 @@ func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes
|
||||||
|
|
||||||
// Add the extra record
|
// Add the extra record
|
||||||
records := d.formatNodeRecord(node.Node, addr, srvRec.Target, dns.TypeANY, ttl)
|
records := d.formatNodeRecord(node.Node, addr, srvRec.Target, dns.TypeANY, ttl)
|
||||||
|
if len(records) > 0 {
|
||||||
if records != nil {
|
|
||||||
// Use the node address if it doesn't differ from the service address
|
// Use the node address if it doesn't differ from the service address
|
||||||
if addr == node.Node.Address {
|
if addr == node.Node.Address {
|
||||||
resp.Extra = append(resp.Extra, records...)
|
resp.Extra = append(resp.Extra, records...)
|
||||||
|
@ -900,6 +899,10 @@ func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes
|
||||||
srvRec.Target = fmt.Sprintf("%s.addr.%s.%s", hex.EncodeToString(record.AAAA), dc, d.domain)
|
srvRec.Target = fmt.Sprintf("%s.addr.%s.%s", hex.EncodeToString(record.AAAA), dc, d.domain)
|
||||||
record.Hdr.Name = srvRec.Target
|
record.Hdr.Name = srvRec.Target
|
||||||
resp.Extra = append(resp.Extra, record)
|
resp.Extra = append(resp.Extra, record)
|
||||||
|
|
||||||
|
// Something else (probably a CNAME; just add the records).
|
||||||
|
default:
|
||||||
|
resp.Extra = append(resp.Extra, records...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -988,7 +988,7 @@ func TestDNS_ExternalServiceToConsulCNAMENestedLookup(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDNS_ServiceLookup_ServiceAddress(t *testing.T) {
|
func TestDNS_ServiceLookup_ServiceAddress_A(t *testing.T) {
|
||||||
dir, srv := makeDNSServer(t)
|
dir, srv := makeDNSServer(t)
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
defer srv.agent.Shutdown()
|
defer srv.agent.Shutdown()
|
||||||
|
@ -1083,6 +1083,101 @@ func TestDNS_ServiceLookup_ServiceAddress(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDNS_ServiceLookup_ServiceAddress_CNAME(t *testing.T) {
|
||||||
|
dir, srv := makeDNSServer(t)
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
defer srv.agent.Shutdown()
|
||||||
|
|
||||||
|
testutil.WaitForLeader(t, srv.agent.RPC, "dc1")
|
||||||
|
|
||||||
|
// Register a node with a service whose address isn't an IP.
|
||||||
|
{
|
||||||
|
args := &structs.RegisterRequest{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
Node: "foo",
|
||||||
|
Address: "127.0.0.1",
|
||||||
|
Service: &structs.NodeService{
|
||||||
|
Service: "db",
|
||||||
|
Tags: []string{"master"},
|
||||||
|
Address: "www.google.com",
|
||||||
|
Port: 12345,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var out struct{}
|
||||||
|
if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register an equivalent prepared query.
|
||||||
|
var id string
|
||||||
|
{
|
||||||
|
args := &structs.PreparedQueryRequest{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
Op: structs.PreparedQueryCreate,
|
||||||
|
Query: &structs.PreparedQuery{
|
||||||
|
Name: "test",
|
||||||
|
Service: structs.ServiceQuery{
|
||||||
|
Service: "db",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := srv.agent.RPC("PreparedQuery.Apply", args, &id); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up the service directly and via prepared query.
|
||||||
|
questions := []string{
|
||||||
|
"db.service.consul.",
|
||||||
|
id + ".query.consul.",
|
||||||
|
}
|
||||||
|
for _, question := range questions {
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetQuestion(question, dns.TypeSRV)
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
|
addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS)
|
||||||
|
in, _, err := c.Exchange(m, addr.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(in.Answer) != 1 {
|
||||||
|
t.Fatalf("Bad: %#v", in)
|
||||||
|
}
|
||||||
|
|
||||||
|
srvRec, ok := in.Answer[0].(*dns.SRV)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Bad: %#v", in.Answer[0])
|
||||||
|
}
|
||||||
|
if srvRec.Port != 12345 {
|
||||||
|
t.Fatalf("Bad: %#v", srvRec)
|
||||||
|
}
|
||||||
|
if srvRec.Target != "foo.node.dc1.consul." {
|
||||||
|
t.Fatalf("Bad: %#v", srvRec)
|
||||||
|
}
|
||||||
|
if srvRec.Hdr.Ttl != 0 {
|
||||||
|
t.Fatalf("Bad: %#v", in.Answer[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
cnameRec, ok := in.Extra[0].(*dns.CNAME)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Bad: %#v", in.Extra[0])
|
||||||
|
}
|
||||||
|
if cnameRec.Hdr.Name != "foo.node.dc1.consul." {
|
||||||
|
t.Fatalf("Bad: %#v", in.Extra[0])
|
||||||
|
}
|
||||||
|
if cnameRec.Target != "www.google.com." {
|
||||||
|
t.Fatalf("Bad: %#v", in.Extra[0])
|
||||||
|
}
|
||||||
|
if cnameRec.Hdr.Ttl != 0 {
|
||||||
|
t.Fatalf("Bad: %#v", in.Extra[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDNS_ServiceLookup_ServiceAddressIPV6(t *testing.T) {
|
func TestDNS_ServiceLookup_ServiceAddressIPV6(t *testing.T) {
|
||||||
dir, srv := makeDNSServer(t)
|
dir, srv := makeDNSServer(t)
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
-------
|
|
||||||
internal/common/binary.go in the gopsutil is copied and modifid from golang/encoding/binary.go.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2009 The Go Authors. 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 Google Inc. 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.
|
|
|
@ -1,26 +0,0 @@
|
||||||
.PHONY: help check
|
|
||||||
.DEFAULT_GOAL := help
|
|
||||||
|
|
||||||
SUBPKGS=cpu disk docker host internal load mem net process
|
|
||||||
|
|
||||||
help: ## Show help
|
|
||||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
|
||||||
|
|
||||||
check: ## Check
|
|
||||||
errcheck -ignore="Close|Run|Write" ./...
|
|
||||||
golint ./... | egrep -v 'underscores|HttpOnly|should have comment|comment on exported|CamelCase|VM|UID' && exit 1 || exit 0
|
|
||||||
|
|
||||||
BUILD_FAIL_PATTERN=grep -v "exec format error" | grep "build failed" && exit 1 || exit 0
|
|
||||||
build_test: ## test only buildable
|
|
||||||
# Supported operating systems
|
|
||||||
GOOS=linux go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
GOOS=freebsd go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
CGO_ENABLED=0 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
GOOS=windows go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
# Operating systems supported for building only (not implemented error if used)
|
|
||||||
GOOS=dragonfly go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
GOOS=netbsd go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
GOOS=solaris go test ./... | $(BUILD_FAIL_PATTERN)
|
|
||||||
@echo 'Successfully built on all known operating systems'
|
|
|
@ -1,11 +0,0 @@
|
||||||
machine:
|
|
||||||
timezone:
|
|
||||||
Asia/Tokyo
|
|
||||||
test:
|
|
||||||
override:
|
|
||||||
- GOOS=linux GOARCH=amd64 go test -v ./...
|
|
||||||
- GOOS=linux GOARCH=386 go get -v ./...
|
|
||||||
- GOOS=linux GOARCH=arm GOARM=7 go get -v ./...
|
|
||||||
- GOOS=freebsd GOARCH=amd64 go get -v ./...
|
|
||||||
- GOOS=windows GOARCH=amd64 go get -v ./...
|
|
||||||
- GOOS=darwin GOARCH=amd64 go get -v ./...
|
|
|
@ -1,26 +0,0 @@
|
||||||
#/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
|
|
|
@ -1 +0,0 @@
|
||||||
package gopsutil
|
|
|
@ -1,50 +0,0 @@
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/internal/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
invoke common.Invoker
|
|
||||||
cachedBootTime = uint64(0)
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
invoke = common.Invoke{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A HostInfoStat describes the host status.
|
|
||||||
// This is not in the psutil but it useful.
|
|
||||||
type InfoStat struct {
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
Uptime uint64 `json:"uptime"`
|
|
||||||
BootTime uint64 `json:"bootTime"`
|
|
||||||
Procs uint64 `json:"procs"` // number of processes
|
|
||||||
OS string `json:"os"` // ex: freebsd, linux
|
|
||||||
Platform string `json:"platform"` // ex: ubuntu, linuxmint
|
|
||||||
PlatformFamily string `json:"platformFamily"` // ex: debian, rhel
|
|
||||||
PlatformVersion string `json:"platformVersion"` // version of the complete OS
|
|
||||||
KernelVersion string `json:"kernelVersion"` // version of the OS kernel (if available)
|
|
||||||
VirtualizationSystem string `json:"virtualizationSystem"`
|
|
||||||
VirtualizationRole string `json:"virtualizationRole"` // guest or host
|
|
||||||
HostID string `json:"hostid"` // ex: uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserStat struct {
|
|
||||||
User string `json:"user"`
|
|
||||||
Terminal string `json:"terminal"`
|
|
||||||
Host string `json:"host"`
|
|
||||||
Started int `json:"started"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h InfoStat) String() string {
|
|
||||||
s, _ := json.Marshal(h)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u UserStat) String() string {
|
|
||||||
s, _ := json.Marshal(u)
|
|
||||||
return string(s)
|
|
||||||
}
|
|
|
@ -1,180 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/internal/common"
|
|
||||||
"github.com/shirou/gopsutil/process"
|
|
||||||
)
|
|
||||||
|
|
||||||
// from utmpx.h
|
|
||||||
const USER_PROCESS = 7
|
|
||||||
|
|
||||||
func Info() (*InfoStat, error) {
|
|
||||||
ret := &InfoStat{
|
|
||||||
OS: runtime.GOOS,
|
|
||||||
PlatformFamily: "darwin",
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err == nil {
|
|
||||||
ret.Hostname = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
platform, family, pver, version, err := PlatformInformation()
|
|
||||||
if err == nil {
|
|
||||||
ret.Platform = platform
|
|
||||||
ret.PlatformFamily = family
|
|
||||||
ret.PlatformVersion = pver
|
|
||||||
ret.KernelVersion = version
|
|
||||||
}
|
|
||||||
|
|
||||||
system, role, err := Virtualization()
|
|
||||||
if err == nil {
|
|
||||||
ret.VirtualizationSystem = system
|
|
||||||
ret.VirtualizationRole = role
|
|
||||||
}
|
|
||||||
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err == nil {
|
|
||||||
ret.BootTime = boot
|
|
||||||
ret.Uptime = uptime(boot)
|
|
||||||
}
|
|
||||||
|
|
||||||
procs, err := process.Pids()
|
|
||||||
if err == nil {
|
|
||||||
ret.Procs = uint64(len(procs))
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := common.DoSysctrl("kern.uuid")
|
|
||||||
if err == nil && len(values) == 1 && values[0] != "" {
|
|
||||||
ret.HostID = values[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
if cachedBootTime != 0 {
|
|
||||||
return cachedBootTime, nil
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
cachedBootTime = uint64(boottime)
|
|
||||||
|
|
||||||
return cachedBootTime, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func uptime(boot uint64) uint64 {
|
|
||||||
return uint64(time.Now().Unix()) - boot
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uptime() (uint64, error) {
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uptime(boot), 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 != USER_PROCESS {
|
|
||||||
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 PlatformInformation() (string, string, string, string, error) {
|
|
||||||
platform := ""
|
|
||||||
family := ""
|
|
||||||
version := ""
|
|
||||||
pver := ""
|
|
||||||
|
|
||||||
sw_vers, err := exec.LookPath("sw_vers")
|
|
||||||
if err != nil {
|
|
||||||
return "", "", "", "", err
|
|
||||||
}
|
|
||||||
uname, err := exec.LookPath("uname")
|
|
||||||
if err != nil {
|
|
||||||
return "", "", "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := invoke.Command(uname, "-s")
|
|
||||||
if err == nil {
|
|
||||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err = invoke.Command(sw_vers, "-productVersion")
|
|
||||||
if err == nil {
|
|
||||||
pver = strings.ToLower(strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err = invoke.Command(uname, "-r")
|
|
||||||
if err == nil {
|
|
||||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return platform, family, pver, version, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Virtualization() (string, string, error) {
|
|
||||||
system := ""
|
|
||||||
role := ""
|
|
||||||
|
|
||||||
return system, role, nil
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
// +build !darwin,!linux,!freebsd,!openbsd,!windows
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import "github.com/shirou/gopsutil/internal/common"
|
|
||||||
|
|
||||||
func Info() (*InfoStat, error) {
|
|
||||||
return nil, common.ErrNotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
return 0, common.ErrNotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uptime() (uint64, error) {
|
|
||||||
return 0, common.ErrNotImplementedError
|
|
||||||
}
|
|
||||||
|
|
||||||
func Users() ([]UserStat, error) {
|
|
||||||
return []UserStat{}, common.ErrNotImplementedError
|
|
||||||
}
|
|
|
@ -1,211 +0,0 @@
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/internal/common"
|
|
||||||
"github.com/shirou/gopsutil/process"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
UTNameSize = 16 /* see MAXLOGNAME in <sys/param.h> */
|
|
||||||
UTLineSize = 8
|
|
||||||
UTHostSize = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
func Info() (*InfoStat, error) {
|
|
||||||
ret := &InfoStat{
|
|
||||||
OS: runtime.GOOS,
|
|
||||||
PlatformFamily: "freebsd",
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err == nil {
|
|
||||||
ret.Hostname = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
platform, family, version, err := PlatformInformation()
|
|
||||||
if err == nil {
|
|
||||||
ret.Platform = platform
|
|
||||||
ret.PlatformFamily = family
|
|
||||||
ret.PlatformVersion = version
|
|
||||||
ret.KernelVersion = version
|
|
||||||
}
|
|
||||||
|
|
||||||
system, role, err := Virtualization()
|
|
||||||
if err == nil {
|
|
||||||
ret.VirtualizationSystem = system
|
|
||||||
ret.VirtualizationRole = role
|
|
||||||
}
|
|
||||||
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err == nil {
|
|
||||||
ret.BootTime = boot
|
|
||||||
ret.Uptime = uptime(boot)
|
|
||||||
}
|
|
||||||
|
|
||||||
procs, err := process.Pids()
|
|
||||||
if err == nil {
|
|
||||||
ret.Procs = uint64(len(procs))
|
|
||||||
}
|
|
||||||
|
|
||||||
values, err := common.DoSysctrl("kern.hostuuid")
|
|
||||||
if err == nil && len(values) == 1 && values[0] != "" {
|
|
||||||
ret.HostID = values[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
if cachedBootTime != 0 {
|
|
||||||
return cachedBootTime, nil
|
|
||||||
}
|
|
||||||
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.ParseUint(v, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
cachedBootTime = boottime
|
|
||||||
|
|
||||||
return boottime, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func uptime(boot uint64) uint64 {
|
|
||||||
return uint64(time.Now().Unix()) - boot
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uptime() (uint64, error) {
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uptime(boot), 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
|
|
||||||
}
|
|
||||||
|
|
||||||
entrySize := sizeOfUtmpx
|
|
||||||
count := len(buf) / entrySize
|
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
b := buf[i*sizeOfUtmpx : (i+1)*sizeOfUtmpx]
|
|
||||||
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 PlatformInformation() (string, string, string, error) {
|
|
||||||
platform := ""
|
|
||||||
family := ""
|
|
||||||
version := ""
|
|
||||||
uname, err := exec.LookPath("uname")
|
|
||||||
if err != nil {
|
|
||||||
return "", "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := invoke.Command(uname, "-s")
|
|
||||||
if err == nil {
|
|
||||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err = invoke.Command(uname, "-r")
|
|
||||||
if err == nil {
|
|
||||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return platform, family, version, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Virtualization() (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
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Created by cgo -godefs - DO NOT EDIT
|
|
||||||
// cgo -godefs types_freebsd.go
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofPtr = 0x4
|
|
||||||
sizeofShort = 0x2
|
|
||||||
sizeofInt = 0x4
|
|
||||||
sizeofLong = 0x4
|
|
||||||
sizeofLongLong = 0x8
|
|
||||||
sizeOfUtmpx = 197 // TODO why should 197
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
_C_short int16
|
|
||||||
_C_int int32
|
|
||||||
_C_long int32
|
|
||||||
_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
|
|
||||||
// X__ut_spare [64]int8
|
|
||||||
}
|
|
||||||
|
|
||||||
type Timeval struct {
|
|
||||||
Sec [4]byte
|
|
||||||
Usec [3]byte
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
// 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
|
|
||||||
sizeOfUtmpx = 197 // TODO: why should 197, not 0x118
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,522 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/internal/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LSB struct {
|
|
||||||
ID string
|
|
||||||
Release string
|
|
||||||
Codename string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
// from utmp.h
|
|
||||||
const USER_PROCESS = 7
|
|
||||||
|
|
||||||
func Info() (*InfoStat, error) {
|
|
||||||
ret := &InfoStat{
|
|
||||||
OS: runtime.GOOS,
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err == nil {
|
|
||||||
ret.Hostname = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
platform, family, version, err := PlatformInformation()
|
|
||||||
if err == nil {
|
|
||||||
ret.Platform = platform
|
|
||||||
ret.PlatformFamily = family
|
|
||||||
ret.PlatformVersion = version
|
|
||||||
}
|
|
||||||
kernelVersion, err := KernelVersion()
|
|
||||||
if err == nil {
|
|
||||||
ret.KernelVersion = kernelVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
system, role, err := Virtualization()
|
|
||||||
if err == nil {
|
|
||||||
ret.VirtualizationSystem = system
|
|
||||||
ret.VirtualizationRole = role
|
|
||||||
}
|
|
||||||
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err == nil {
|
|
||||||
ret.BootTime = boot
|
|
||||||
ret.Uptime = uptime(boot)
|
|
||||||
}
|
|
||||||
|
|
||||||
if numProcs, err := common.NumProcs(); err == nil {
|
|
||||||
ret.Procs = numProcs
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// BootTime returns the system boot time expressed in seconds since the epoch.
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
if cachedBootTime != 0 {
|
|
||||||
return cachedBootTime, nil
|
|
||||||
}
|
|
||||||
filename := common.HostProc("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
|
|
||||||
}
|
|
||||||
cachedBootTime = uint64(b)
|
|
||||||
return cachedBootTime, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, fmt.Errorf("could not find btime")
|
|
||||||
}
|
|
||||||
|
|
||||||
func uptime(boot uint64) uint64 {
|
|
||||||
return uint64(time.Now().Unix()) - boot
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uptime() (uint64, error) {
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uptime(boot), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
count := len(buf) / sizeOfUtmp
|
|
||||||
|
|
||||||
ret := make([]UserStat, 0, count)
|
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
b := buf[i*sizeOfUtmp : (i+1)*sizeOfUtmp]
|
|
||||||
|
|
||||||
var u utmp
|
|
||||||
br := bytes.NewReader(b)
|
|
||||||
err := binary.Read(br, binary.LittleEndian, &u)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if u.Type != USER_PROCESS {
|
|
||||||
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 getOSRelease() (platform string, version string, err error) {
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("os-release"))
|
|
||||||
if err != nil {
|
|
||||||
return "", "", nil // return empty
|
|
||||||
}
|
|
||||||
for _, line := range contents {
|
|
||||||
field := strings.Split(line, "=")
|
|
||||||
if len(field) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch field[0] {
|
|
||||||
case "ID": // use ID for lowercase
|
|
||||||
platform = field[1]
|
|
||||||
case "VERSION":
|
|
||||||
version = field[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return platform, version, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLSB() (*LSB, error) {
|
|
||||||
ret := &LSB{}
|
|
||||||
if common.PathExists(common.HostEtc("lsb-release")) {
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("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") {
|
|
||||||
lsb_release, err := exec.LookPath("/usr/bin/lsb_release")
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
out, err := invoke.Command(lsb_release)
|
|
||||||
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 PlatformInformation() (platform string, family string, version string, err error) {
|
|
||||||
|
|
||||||
lsb, err := getLSB()
|
|
||||||
if err != nil {
|
|
||||||
lsb = &LSB{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if common.PathExists(common.HostEtc("oracle-release")) {
|
|
||||||
platform = "oracle"
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("oracle-release"))
|
|
||||||
if err == nil {
|
|
||||||
version = getRedhatishVersion(contents)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if common.PathExists(common.HostEtc("enterprise-release")) {
|
|
||||||
platform = "oracle"
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("enterprise-release"))
|
|
||||||
if err == nil {
|
|
||||||
version = getRedhatishVersion(contents)
|
|
||||||
}
|
|
||||||
} else if common.PathExists(common.HostEtc("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(common.HostEtc("debian_version"))
|
|
||||||
if err == nil {
|
|
||||||
version = contents[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if common.PathExists(common.HostEtc("redhat-release")) {
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("redhat-release"))
|
|
||||||
if err == nil {
|
|
||||||
version = getRedhatishVersion(contents)
|
|
||||||
platform = getRedhatishPlatform(contents)
|
|
||||||
}
|
|
||||||
} else if common.PathExists(common.HostEtc("system-release")) {
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("system-release"))
|
|
||||||
if err == nil {
|
|
||||||
version = getRedhatishVersion(contents)
|
|
||||||
platform = getRedhatishPlatform(contents)
|
|
||||||
}
|
|
||||||
} else if common.PathExists(common.HostEtc("gentoo-release")) {
|
|
||||||
platform = "gentoo"
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("gentoo-release"))
|
|
||||||
if err == nil {
|
|
||||||
version = getRedhatishVersion(contents)
|
|
||||||
}
|
|
||||||
} else if common.PathExists(common.HostEtc("SuSE-release")) {
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("SuSE-release"))
|
|
||||||
if err == nil {
|
|
||||||
version = getSuseVersion(contents)
|
|
||||||
platform = getSusePlatform(contents)
|
|
||||||
}
|
|
||||||
// TODO: slackware detecion
|
|
||||||
} else if common.PathExists(common.HostEtc("arch-release")) {
|
|
||||||
platform = "arch"
|
|
||||||
version = lsb.Release
|
|
||||||
} else if common.PathExists(common.HostEtc("alpine-release")) {
|
|
||||||
platform = "alpine"
|
|
||||||
contents, err := common.ReadLines(common.HostEtc("alpine-release"))
|
|
||||||
if err == nil && len(contents) > 0 {
|
|
||||||
version = contents[0]
|
|
||||||
}
|
|
||||||
} else if common.PathExists(common.HostEtc("os-release")) {
|
|
||||||
p, v, err := getOSRelease()
|
|
||||||
if err == nil {
|
|
||||||
platform = p
|
|
||||||
version = v
|
|
||||||
}
|
|
||||||
} 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"
|
|
||||||
case "alpine":
|
|
||||||
family = "alpine"
|
|
||||||
case "coreos":
|
|
||||||
family = "coreos"
|
|
||||||
}
|
|
||||||
|
|
||||||
return platform, family, version, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func KernelVersion() (version string, err error) {
|
|
||||||
filename := common.HostProc("sys/kernel/osrelease")
|
|
||||||
if common.PathExists(filename) {
|
|
||||||
contents, err := common.ReadLines(filename)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(contents) > 0 {
|
|
||||||
version = contents[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 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 Virtualization() (string, string, error) {
|
|
||||||
var system string
|
|
||||||
var role string
|
|
||||||
|
|
||||||
filename := common.HostProc("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.StringsContains(contents, "control_d") {
|
|
||||||
role = "host"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = common.HostProc("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.HostProc("cpuinfo")
|
|
||||||
if common.PathExists(filename) {
|
|
||||||
contents, err := common.ReadLines(filename)
|
|
||||||
if err == nil {
|
|
||||||
if common.StringsContains(contents, "QEMU Virtual CPU") ||
|
|
||||||
common.StringsContains(contents, "Common KVM processor") ||
|
|
||||||
common.StringsContains(contents, "Common 32-bit KVM processor") {
|
|
||||||
system = "kvm"
|
|
||||||
role = "guest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = common.HostProc()
|
|
||||||
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.StringsContains(contents, "s_context:") ||
|
|
||||||
common.StringsContains(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.StringsContains(contents, "lxc") {
|
|
||||||
system = "lxc"
|
|
||||||
role = "guest"
|
|
||||||
} else if common.StringsContains(contents, "docker") {
|
|
||||||
system = "docker"
|
|
||||||
role = "guest"
|
|
||||||
} else if common.StringsContains(contents, "machine-rkt") {
|
|
||||||
system = "rkt"
|
|
||||||
role = "guest"
|
|
||||||
} else if common.PathExists("/usr/bin/lxc-version") {
|
|
||||||
system = "lxc"
|
|
||||||
role = "host"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if common.PathExists(common.HostEtc("os-release")) {
|
|
||||||
p, _, err := getOSRelease()
|
|
||||||
if err == nil && p == "coreos" {
|
|
||||||
system = "rkt" // Is it true?
|
|
||||||
role = "host"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return system, role, nil
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
// 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
|
|
||||||
sizeOfUtmp = 0x180
|
|
||||||
)
|
|
||||||
|
|
||||||
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 {
|
|
||||||
Sec int32
|
|
||||||
Usec int32
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
// 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
|
|
||||||
sizeOfUtmp = 0x180
|
|
||||||
)
|
|
||||||
|
|
||||||
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 _Ctype_struct___0
|
|
||||||
Addr_v6 [4]int32
|
|
||||||
X__glibc_reserved [20]int8
|
|
||||||
}
|
|
||||||
type exit_status struct {
|
|
||||||
Termination int16
|
|
||||||
Exit int16
|
|
||||||
}
|
|
||||||
type timeval struct {
|
|
||||||
Sec int64
|
|
||||||
Usec int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type _Ctype_struct___0 struct {
|
|
||||||
Sec int32
|
|
||||||
Usec int32
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Created by cgo -godefs - DO NOT EDIT
|
|
||||||
// cgo -godefs types_linux.go | sed "s/uint8/int8/g"
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofPtr = 0x4
|
|
||||||
sizeofShort = 0x2
|
|
||||||
sizeofInt = 0x4
|
|
||||||
sizeofLong = 0x4
|
|
||||||
sizeofLongLong = 0x8
|
|
||||||
sizeOfUtmp = 0x180
|
|
||||||
)
|
|
||||||
|
|
||||||
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 timeval
|
|
||||||
Addr_v6 [4]int32
|
|
||||||
X__glibc_reserved [20]int8
|
|
||||||
}
|
|
||||||
type exit_status struct {
|
|
||||||
Termination int16
|
|
||||||
Exit int16
|
|
||||||
}
|
|
||||||
type timeval struct {
|
|
||||||
Sec int32
|
|
||||||
Usec int32
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// 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
|
|
||||||
sizeOfUtmp = 0x180
|
|
||||||
)
|
|
||||||
|
|
||||||
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 timeval
|
|
||||||
Addr_v6 [4]int32
|
|
||||||
X__glibc_reserved [20]int8
|
|
||||||
}
|
|
||||||
type exit_status struct {
|
|
||||||
Termination int16
|
|
||||||
Exit int16
|
|
||||||
}
|
|
||||||
type timeval struct {
|
|
||||||
Sec int64
|
|
||||||
Usec int64
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build ppc64le
|
|
||||||
// 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
|
|
||||||
sizeOfUtmp = 0x180
|
|
||||||
)
|
|
||||||
|
|
||||||
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 timeval
|
|
||||||
Addr_v6 [4]int32
|
|
||||||
X__glibc_reserved [20]int8
|
|
||||||
}
|
|
||||||
type exit_status struct {
|
|
||||||
Termination int16
|
|
||||||
Exit int16
|
|
||||||
}
|
|
||||||
type timeval struct {
|
|
||||||
Sec int64
|
|
||||||
Usec int64
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build s390x
|
|
||||||
// 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
|
|
||||||
sizeOfUtmp = 0x180
|
|
||||||
)
|
|
||||||
|
|
||||||
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 timeval
|
|
||||||
Addr_v6 [4]int32
|
|
||||||
X__glibc_reserved [20]int8
|
|
||||||
}
|
|
||||||
type exit_status struct {
|
|
||||||
Termination int16
|
|
||||||
Exit int16
|
|
||||||
}
|
|
||||||
type timeval struct {
|
|
||||||
Sec int64
|
|
||||||
Usec int64
|
|
||||||
}
|
|
|
@ -1,154 +0,0 @@
|
||||||
// +build openbsd
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/internal/common"
|
|
||||||
"github.com/shirou/gopsutil/process"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
UTNameSize = 32 /* see MAXLOGNAME in <sys/param.h> */
|
|
||||||
UTLineSize = 8
|
|
||||||
UTHostSize = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
func Info() (*InfoStat, error) {
|
|
||||||
ret := &InfoStat{
|
|
||||||
OS: runtime.GOOS,
|
|
||||||
PlatformFamily: "openbsd",
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err == nil {
|
|
||||||
ret.Hostname = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
platform, family, version, err := PlatformInformation()
|
|
||||||
if err == nil {
|
|
||||||
ret.Platform = platform
|
|
||||||
ret.PlatformFamily = family
|
|
||||||
ret.PlatformVersion = version
|
|
||||||
}
|
|
||||||
system, role, err := Virtualization()
|
|
||||||
if err == nil {
|
|
||||||
ret.VirtualizationSystem = system
|
|
||||||
ret.VirtualizationRole = role
|
|
||||||
}
|
|
||||||
|
|
||||||
procs, err := process.Pids()
|
|
||||||
if err == nil {
|
|
||||||
ret.Procs = uint64(len(procs))
|
|
||||||
}
|
|
||||||
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err == nil {
|
|
||||||
ret.BootTime = boot
|
|
||||||
ret.Uptime = uptime(boot)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
val, err := common.DoSysctrl("kern.boottime")
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
boottime, err := strconv.ParseUint(val[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return boottime, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func uptime(boot uint64) uint64 {
|
|
||||||
return uint64(time.Now().Unix()) - boot
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uptime() (uint64, error) {
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uptime(boot), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PlatformInformation() (string, string, string, error) {
|
|
||||||
platform := ""
|
|
||||||
family := ""
|
|
||||||
version := ""
|
|
||||||
uname, err := exec.LookPath("uname")
|
|
||||||
if err != nil {
|
|
||||||
return "", "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := invoke.Command(uname, "-s")
|
|
||||||
if err == nil {
|
|
||||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err = invoke.Command(uname, "-r")
|
|
||||||
if err == nil {
|
|
||||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return platform, family, version, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Virtualization() (string, string, error) {
|
|
||||||
system := ""
|
|
||||||
role := ""
|
|
||||||
|
|
||||||
return system, role, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Users() ([]UserStat, error) {
|
|
||||||
var ret []UserStat
|
|
||||||
utmpfile := "/var/run/utmp"
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
// Created by cgo -godefs - DO NOT EDIT
|
|
||||||
// cgo -godefs types_openbsd.go
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofPtr = 0x8
|
|
||||||
sizeofShort = 0x2
|
|
||||||
sizeofInt = 0x4
|
|
||||||
sizeofLong = 0x8
|
|
||||||
sizeofLongLong = 0x8
|
|
||||||
sizeOfUtmp = 0x130
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
_C_short int16
|
|
||||||
_C_int int32
|
|
||||||
_C_long int64
|
|
||||||
_C_long_long int64
|
|
||||||
)
|
|
||||||
|
|
||||||
type Utmp struct {
|
|
||||||
Line [8]int8
|
|
||||||
Name [32]int8
|
|
||||||
Host [256]int8
|
|
||||||
Time int64
|
|
||||||
}
|
|
||||||
type Timeval struct {
|
|
||||||
Sec int64
|
|
||||||
Usec int64
|
|
||||||
}
|
|
|
@ -1,137 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/StackExchange/wmi"
|
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/internal/common"
|
|
||||||
process "github.com/shirou/gopsutil/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 Info() (*InfoStat, error) {
|
|
||||||
ret := &InfoStat{
|
|
||||||
OS: runtime.GOOS,
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err == nil {
|
|
||||||
ret.Hostname = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
platform, family, version, err := PlatformInformation()
|
|
||||||
if err == nil {
|
|
||||||
ret.Platform = platform
|
|
||||||
ret.PlatformFamily = family
|
|
||||||
ret.PlatformVersion = version
|
|
||||||
} else {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
boot, err := BootTime()
|
|
||||||
if err == nil {
|
|
||||||
ret.BootTime = boot
|
|
||||||
ret.Uptime, _ = Uptime()
|
|
||||||
}
|
|
||||||
|
|
||||||
procs, err := process.Pids()
|
|
||||||
if err == nil {
|
|
||||||
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 Uptime() (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 bootTime(up uint64) uint64 {
|
|
||||||
return uint64(time.Now().Unix()) - up
|
|
||||||
}
|
|
||||||
|
|
||||||
func BootTime() (uint64, error) {
|
|
||||||
if cachedBootTime != 0 {
|
|
||||||
return cachedBootTime, nil
|
|
||||||
}
|
|
||||||
up, err := Uptime()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
cachedBootTime = bootTime(up)
|
|
||||||
return cachedBootTime, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PlatformInformation() (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
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
// +build ignore
|
|
||||||
// plus hand editing about timeval
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <utmpx.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type Utmpx C.struct_utmpx
|
|
||||||
type Timeval C.struct_timeval
|
|
|
@ -1,44 +0,0 @@
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define KERNEL
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <utmpx.h>
|
|
||||||
|
|
||||||
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
|
|
||||||
sizeOfUtmpx = C.sizeof_struct_utmpx
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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
|
|
|
@ -1,42 +0,0 @@
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <utmp.h>
|
|
||||||
|
|
||||||
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
|
|
||||||
sizeOfUtmp = C.sizeof_struct_utmp
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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 timeval C.struct_timeval
|
|
|
@ -1,43 +0,0 @@
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input to cgo -godefs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package host
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define KERNEL
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <utmp.h>
|
|
||||||
|
|
||||||
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
|
|
||||||
sizeOfUtmp = C.sizeof_struct_utmp
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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 Timeval C.struct_timeval
|
|
|
@ -1,634 +0,0 @@
|
||||||
package common
|
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package binary implements simple translation between numbers and byte
|
|
||||||
// sequences and encoding and decoding of varints.
|
|
||||||
//
|
|
||||||
// Numbers are translated by reading and writing fixed-size values.
|
|
||||||
// A fixed-size value is either a fixed-size arithmetic
|
|
||||||
// type (int8, uint8, int16, float32, complex64, ...)
|
|
||||||
// or an array or struct containing only fixed-size values.
|
|
||||||
//
|
|
||||||
// The varint functions encode and decode single integer values using
|
|
||||||
// a variable-length encoding; smaller values require fewer bytes.
|
|
||||||
// For a specification, see
|
|
||||||
// http://code.google.com/apis/protocolbuffers/docs/encoding.html.
|
|
||||||
//
|
|
||||||
// This package favors simplicity over efficiency. Clients that require
|
|
||||||
// high-performance serialization, especially for large data structures,
|
|
||||||
// should look at more advanced solutions such as the encoding/gob
|
|
||||||
// package or protocol buffers.
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A ByteOrder specifies how to convert byte sequences into
|
|
||||||
// 16-, 32-, or 64-bit unsigned integers.
|
|
||||||
type ByteOrder interface {
|
|
||||||
Uint16([]byte) uint16
|
|
||||||
Uint32([]byte) uint32
|
|
||||||
Uint64([]byte) uint64
|
|
||||||
PutUint16([]byte, uint16)
|
|
||||||
PutUint32([]byte, uint32)
|
|
||||||
PutUint64([]byte, uint64)
|
|
||||||
String() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// LittleEndian is the little-endian implementation of ByteOrder.
|
|
||||||
var LittleEndian littleEndian
|
|
||||||
|
|
||||||
// BigEndian is the big-endian implementation of ByteOrder.
|
|
||||||
var BigEndian bigEndian
|
|
||||||
|
|
||||||
type littleEndian struct{}
|
|
||||||
|
|
||||||
func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
|
|
||||||
|
|
||||||
func (littleEndian) PutUint16(b []byte, v uint16) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) Uint32(b []byte) uint32 {
|
|
||||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) PutUint32(b []byte, v uint32) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
b[2] = byte(v >> 16)
|
|
||||||
b[3] = byte(v >> 24)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) Uint64(b []byte) uint64 {
|
|
||||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
|
||||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) PutUint64(b []byte, v uint64) {
|
|
||||||
b[0] = byte(v)
|
|
||||||
b[1] = byte(v >> 8)
|
|
||||||
b[2] = byte(v >> 16)
|
|
||||||
b[3] = byte(v >> 24)
|
|
||||||
b[4] = byte(v >> 32)
|
|
||||||
b[5] = byte(v >> 40)
|
|
||||||
b[6] = byte(v >> 48)
|
|
||||||
b[7] = byte(v >> 56)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (littleEndian) String() string { return "LittleEndian" }
|
|
||||||
|
|
||||||
func (littleEndian) GoString() string { return "binary.LittleEndian" }
|
|
||||||
|
|
||||||
type bigEndian struct{}
|
|
||||||
|
|
||||||
func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
|
|
||||||
|
|
||||||
func (bigEndian) PutUint16(b []byte, v uint16) {
|
|
||||||
b[0] = byte(v >> 8)
|
|
||||||
b[1] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) Uint32(b []byte) uint32 {
|
|
||||||
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) PutUint32(b []byte, v uint32) {
|
|
||||||
b[0] = byte(v >> 24)
|
|
||||||
b[1] = byte(v >> 16)
|
|
||||||
b[2] = byte(v >> 8)
|
|
||||||
b[3] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) Uint64(b []byte) uint64 {
|
|
||||||
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
|
||||||
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) PutUint64(b []byte, v uint64) {
|
|
||||||
b[0] = byte(v >> 56)
|
|
||||||
b[1] = byte(v >> 48)
|
|
||||||
b[2] = byte(v >> 40)
|
|
||||||
b[3] = byte(v >> 32)
|
|
||||||
b[4] = byte(v >> 24)
|
|
||||||
b[5] = byte(v >> 16)
|
|
||||||
b[6] = byte(v >> 8)
|
|
||||||
b[7] = byte(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bigEndian) String() string { return "BigEndian" }
|
|
||||||
|
|
||||||
func (bigEndian) GoString() string { return "binary.BigEndian" }
|
|
||||||
|
|
||||||
// Read reads structured binary data from r into data.
|
|
||||||
// Data must be a pointer to a fixed-size value or a slice
|
|
||||||
// of fixed-size values.
|
|
||||||
// Bytes read from r are decoded using the specified byte order
|
|
||||||
// and written to successive fields of the data.
|
|
||||||
// When reading into structs, the field data for fields with
|
|
||||||
// blank (_) field names is skipped; i.e., blank field names
|
|
||||||
// may be used for padding.
|
|
||||||
// When reading into a struct, all non-blank fields must be exported.
|
|
||||||
func Read(r io.Reader, order ByteOrder, data interface{}) error {
|
|
||||||
// Fast path for basic types and slices.
|
|
||||||
if n := intDataSize(data); n != 0 {
|
|
||||||
var b [8]byte
|
|
||||||
var bs []byte
|
|
||||||
if n > len(b) {
|
|
||||||
bs = make([]byte, n)
|
|
||||||
} else {
|
|
||||||
bs = b[:n]
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(r, bs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch data := data.(type) {
|
|
||||||
case *int8:
|
|
||||||
*data = int8(b[0])
|
|
||||||
case *uint8:
|
|
||||||
*data = b[0]
|
|
||||||
case *int16:
|
|
||||||
*data = int16(order.Uint16(bs))
|
|
||||||
case *uint16:
|
|
||||||
*data = order.Uint16(bs)
|
|
||||||
case *int32:
|
|
||||||
*data = int32(order.Uint32(bs))
|
|
||||||
case *uint32:
|
|
||||||
*data = order.Uint32(bs)
|
|
||||||
case *int64:
|
|
||||||
*data = int64(order.Uint64(bs))
|
|
||||||
case *uint64:
|
|
||||||
*data = order.Uint64(bs)
|
|
||||||
case []int8:
|
|
||||||
for i, x := range bs { // Easier to loop over the input for 8-bit values.
|
|
||||||
data[i] = int8(x)
|
|
||||||
}
|
|
||||||
case []uint8:
|
|
||||||
copy(data, bs)
|
|
||||||
case []int16:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int16(order.Uint16(bs[2*i:]))
|
|
||||||
}
|
|
||||||
case []uint16:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint16(bs[2*i:])
|
|
||||||
}
|
|
||||||
case []int32:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int32(order.Uint32(bs[4*i:]))
|
|
||||||
}
|
|
||||||
case []uint32:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint32(bs[4*i:])
|
|
||||||
}
|
|
||||||
case []int64:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = int64(order.Uint64(bs[8*i:]))
|
|
||||||
}
|
|
||||||
case []uint64:
|
|
||||||
for i := range data {
|
|
||||||
data[i] = order.Uint64(bs[8*i:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to reflect-based decoding.
|
|
||||||
v := reflect.ValueOf(data)
|
|
||||||
size := -1
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
v = v.Elem()
|
|
||||||
size = dataSize(v)
|
|
||||||
case reflect.Slice:
|
|
||||||
size = dataSize(v)
|
|
||||||
}
|
|
||||||
if size < 0 {
|
|
||||||
return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
|
|
||||||
}
|
|
||||||
d := &decoder{order: order, buf: make([]byte, size)}
|
|
||||||
if _, err := io.ReadFull(r, d.buf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.value(v)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes the binary representation of data into w.
|
|
||||||
// Data must be a fixed-size value or a slice of fixed-size
|
|
||||||
// values, or a pointer to such data.
|
|
||||||
// Bytes written to w are encoded using the specified byte order
|
|
||||||
// and read from successive fields of the data.
|
|
||||||
// When writing structs, zero values are written for fields
|
|
||||||
// with blank (_) field names.
|
|
||||||
func Write(w io.Writer, order ByteOrder, data interface{}) error {
|
|
||||||
// Fast path for basic types and slices.
|
|
||||||
if n := intDataSize(data); n != 0 {
|
|
||||||
var b [8]byte
|
|
||||||
var bs []byte
|
|
||||||
if n > len(b) {
|
|
||||||
bs = make([]byte, n)
|
|
||||||
} else {
|
|
||||||
bs = b[:n]
|
|
||||||
}
|
|
||||||
switch v := data.(type) {
|
|
||||||
case *int8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(*v)
|
|
||||||
case int8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(v)
|
|
||||||
case []int8:
|
|
||||||
for i, x := range v {
|
|
||||||
bs[i] = byte(x)
|
|
||||||
}
|
|
||||||
case *uint8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = *v
|
|
||||||
case uint8:
|
|
||||||
bs = b[:1]
|
|
||||||
b[0] = byte(v)
|
|
||||||
case []uint8:
|
|
||||||
bs = v
|
|
||||||
case *int16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, uint16(*v))
|
|
||||||
case int16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, uint16(v))
|
|
||||||
case []int16:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint16(bs[2*i:], uint16(x))
|
|
||||||
}
|
|
||||||
case *uint16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, *v)
|
|
||||||
case uint16:
|
|
||||||
bs = b[:2]
|
|
||||||
order.PutUint16(bs, v)
|
|
||||||
case []uint16:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint16(bs[2*i:], x)
|
|
||||||
}
|
|
||||||
case *int32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, uint32(*v))
|
|
||||||
case int32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, uint32(v))
|
|
||||||
case []int32:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint32(bs[4*i:], uint32(x))
|
|
||||||
}
|
|
||||||
case *uint32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, *v)
|
|
||||||
case uint32:
|
|
||||||
bs = b[:4]
|
|
||||||
order.PutUint32(bs, v)
|
|
||||||
case []uint32:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint32(bs[4*i:], x)
|
|
||||||
}
|
|
||||||
case *int64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, uint64(*v))
|
|
||||||
case int64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, uint64(v))
|
|
||||||
case []int64:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint64(bs[8*i:], uint64(x))
|
|
||||||
}
|
|
||||||
case *uint64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, *v)
|
|
||||||
case uint64:
|
|
||||||
bs = b[:8]
|
|
||||||
order.PutUint64(bs, v)
|
|
||||||
case []uint64:
|
|
||||||
for i, x := range v {
|
|
||||||
order.PutUint64(bs[8*i:], x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err := w.Write(bs)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to reflect-based encoding.
|
|
||||||
v := reflect.Indirect(reflect.ValueOf(data))
|
|
||||||
size := dataSize(v)
|
|
||||||
if size < 0 {
|
|
||||||
return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
|
|
||||||
}
|
|
||||||
buf := make([]byte, size)
|
|
||||||
e := &encoder{order: order, buf: buf}
|
|
||||||
e.value(v)
|
|
||||||
_, err := w.Write(buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns how many bytes Write would generate to encode the value v, which
|
|
||||||
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
|
|
||||||
// If v is neither of these, Size returns -1.
|
|
||||||
func Size(v interface{}) int {
|
|
||||||
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
|
|
||||||
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
|
|
||||||
// it returns the length of the slice times the element size and does not count the memory
|
|
||||||
// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
|
|
||||||
func dataSize(v reflect.Value) int {
|
|
||||||
if v.Kind() == reflect.Slice {
|
|
||||||
if s := sizeof(v.Type().Elem()); s >= 0 {
|
|
||||||
return s * v.Len()
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return sizeof(v.Type())
|
|
||||||
}
|
|
||||||
|
|
||||||
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
|
|
||||||
func sizeof(t reflect.Type) int {
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
if s := sizeof(t.Elem()); s >= 0 {
|
|
||||||
return s * t.Len()
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
sum := 0
|
|
||||||
for i, n := 0, t.NumField(); i < n; i++ {
|
|
||||||
s := sizeof(t.Field(i).Type)
|
|
||||||
if s < 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
sum += s
|
|
||||||
}
|
|
||||||
return sum
|
|
||||||
|
|
||||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
|
||||||
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr:
|
|
||||||
return int(t.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
type coder struct {
|
|
||||||
order ByteOrder
|
|
||||||
buf []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type decoder coder
|
|
||||||
type encoder coder
|
|
||||||
|
|
||||||
func (d *decoder) uint8() uint8 {
|
|
||||||
x := d.buf[0]
|
|
||||||
d.buf = d.buf[1:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint8(x uint8) {
|
|
||||||
e.buf[0] = x
|
|
||||||
e.buf = e.buf[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint16() uint16 {
|
|
||||||
x := d.order.Uint16(d.buf[0:2])
|
|
||||||
d.buf = d.buf[2:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint16(x uint16) {
|
|
||||||
e.order.PutUint16(e.buf[0:2], x)
|
|
||||||
e.buf = e.buf[2:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint32() uint32 {
|
|
||||||
x := d.order.Uint32(d.buf[0:4])
|
|
||||||
d.buf = d.buf[4:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint32(x uint32) {
|
|
||||||
e.order.PutUint32(e.buf[0:4], x)
|
|
||||||
e.buf = e.buf[4:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) uint64() uint64 {
|
|
||||||
x := d.order.Uint64(d.buf[0:8])
|
|
||||||
d.buf = d.buf[8:]
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) uint64(x uint64) {
|
|
||||||
e.order.PutUint64(e.buf[0:8], x)
|
|
||||||
e.buf = e.buf[8:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) int8() int8 { return int8(d.uint8()) }
|
|
||||||
|
|
||||||
func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int16() int16 { return int16(d.uint16()) }
|
|
||||||
|
|
||||||
func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int32() int32 { return int32(d.uint32()) }
|
|
||||||
|
|
||||||
func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) int64() int64 { return int64(d.uint64()) }
|
|
||||||
|
|
||||||
func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
|
|
||||||
|
|
||||||
func (d *decoder) value(v reflect.Value) {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
d.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
t := v.Type()
|
|
||||||
l := v.NumField()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
// Note: Calling v.CanSet() below is an optimization.
|
|
||||||
// It would be sufficient to check the field name,
|
|
||||||
// but creating the StructField info for each field is
|
|
||||||
// costly (run "go test -bench=ReadStruct" and compare
|
|
||||||
// results when making changes to this code).
|
|
||||||
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
|
||||||
d.value(v)
|
|
||||||
} else {
|
|
||||||
d.skip(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
d.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int8:
|
|
||||||
v.SetInt(int64(d.int8()))
|
|
||||||
case reflect.Int16:
|
|
||||||
v.SetInt(int64(d.int16()))
|
|
||||||
case reflect.Int32:
|
|
||||||
v.SetInt(int64(d.int32()))
|
|
||||||
case reflect.Int64:
|
|
||||||
v.SetInt(d.int64())
|
|
||||||
|
|
||||||
case reflect.Uint8:
|
|
||||||
v.SetUint(uint64(d.uint8()))
|
|
||||||
case reflect.Uint16:
|
|
||||||
v.SetUint(uint64(d.uint16()))
|
|
||||||
case reflect.Uint32:
|
|
||||||
v.SetUint(uint64(d.uint32()))
|
|
||||||
case reflect.Uint64:
|
|
||||||
v.SetUint(d.uint64())
|
|
||||||
|
|
||||||
case reflect.Float32:
|
|
||||||
v.SetFloat(float64(math.Float32frombits(d.uint32())))
|
|
||||||
case reflect.Float64:
|
|
||||||
v.SetFloat(math.Float64frombits(d.uint64()))
|
|
||||||
|
|
||||||
case reflect.Complex64:
|
|
||||||
v.SetComplex(complex(
|
|
||||||
float64(math.Float32frombits(d.uint32())),
|
|
||||||
float64(math.Float32frombits(d.uint32())),
|
|
||||||
))
|
|
||||||
case reflect.Complex128:
|
|
||||||
v.SetComplex(complex(
|
|
||||||
math.Float64frombits(d.uint64()),
|
|
||||||
math.Float64frombits(d.uint64()),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) value(v reflect.Value) {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
e.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
t := v.Type()
|
|
||||||
l := v.NumField()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
// see comment for corresponding code in decoder.value()
|
|
||||||
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
|
||||||
e.value(v)
|
|
||||||
} else {
|
|
||||||
e.skip(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
l := v.Len()
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
e.value(v.Index(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Int8:
|
|
||||||
e.int8(int8(v.Int()))
|
|
||||||
case reflect.Int16:
|
|
||||||
e.int16(int16(v.Int()))
|
|
||||||
case reflect.Int32:
|
|
||||||
e.int32(int32(v.Int()))
|
|
||||||
case reflect.Int64:
|
|
||||||
e.int64(v.Int())
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Uint8:
|
|
||||||
e.uint8(uint8(v.Uint()))
|
|
||||||
case reflect.Uint16:
|
|
||||||
e.uint16(uint16(v.Uint()))
|
|
||||||
case reflect.Uint32:
|
|
||||||
e.uint32(uint32(v.Uint()))
|
|
||||||
case reflect.Uint64:
|
|
||||||
e.uint64(v.Uint())
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Float32:
|
|
||||||
e.uint32(math.Float32bits(float32(v.Float())))
|
|
||||||
case reflect.Float64:
|
|
||||||
e.uint64(math.Float64bits(v.Float()))
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Complex64, reflect.Complex128:
|
|
||||||
switch v.Type().Kind() {
|
|
||||||
case reflect.Complex64:
|
|
||||||
x := v.Complex()
|
|
||||||
e.uint32(math.Float32bits(float32(real(x))))
|
|
||||||
e.uint32(math.Float32bits(float32(imag(x))))
|
|
||||||
case reflect.Complex128:
|
|
||||||
x := v.Complex()
|
|
||||||
e.uint64(math.Float64bits(real(x)))
|
|
||||||
e.uint64(math.Float64bits(imag(x)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) skip(v reflect.Value) {
|
|
||||||
d.buf = d.buf[dataSize(v):]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encoder) skip(v reflect.Value) {
|
|
||||||
n := dataSize(v)
|
|
||||||
for i := range e.buf[0:n] {
|
|
||||||
e.buf[i] = 0
|
|
||||||
}
|
|
||||||
e.buf = e.buf[n:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// intDataSize returns the size of the data required to represent the data when encoded.
|
|
||||||
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
|
|
||||||
func intDataSize(data interface{}) int {
|
|
||||||
switch data := data.(type) {
|
|
||||||
case int8, *int8, *uint8:
|
|
||||||
return 1
|
|
||||||
case []int8:
|
|
||||||
return len(data)
|
|
||||||
case []uint8:
|
|
||||||
return len(data)
|
|
||||||
case int16, *int16, *uint16:
|
|
||||||
return 2
|
|
||||||
case []int16:
|
|
||||||
return 2 * len(data)
|
|
||||||
case []uint16:
|
|
||||||
return 2 * len(data)
|
|
||||||
case int32, *int32, *uint32:
|
|
||||||
return 4
|
|
||||||
case []int32:
|
|
||||||
return 4 * len(data)
|
|
||||||
case []uint32:
|
|
||||||
return 4 * len(data)
|
|
||||||
case int64, *int64, *uint64:
|
|
||||||
return 8
|
|
||||||
case []int64:
|
|
||||||
return 8 * len(data)
|
|
||||||
case []uint64:
|
|
||||||
return 8 * len(data)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,386 +0,0 @@
|
||||||
package common
|
|
||||||
|
|
||||||
//
|
|
||||||
// gopsutil is a port of psutil(http://pythonhosted.org/psutil/).
|
|
||||||
// This covers these architectures.
|
|
||||||
// - linux (amd64, arm)
|
|
||||||
// - freebsd (amd64)
|
|
||||||
// - windows (amd64)
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Timeout = 3 * time.Second
|
|
||||||
ErrTimeout = errors.New("Command timed out.")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Invoker interface {
|
|
||||||
Command(string, ...string) ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Invoke struct{}
|
|
||||||
|
|
||||||
func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
|
|
||||||
cmd := exec.Command(name, arg...)
|
|
||||||
return CombinedOutputTimeout(cmd, Timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
return exec.Command(name, arg...).Output()
|
|
||||||
}
|
|
||||||
|
|
||||||
var ErrNotImplementedError = 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 UintToString(orig []uint8) 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])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadInts reads contents from single line file and returns them as []int32.
|
|
||||||
func ReadInts(filename string) ([]int64, error) {
|
|
||||||
f, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return []int64{}, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
var ret []int64
|
|
||||||
|
|
||||||
r := bufio.NewReader(f)
|
|
||||||
|
|
||||||
// The int files that this is concerned with should only be one liners.
|
|
||||||
line, err := r.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
return []int64{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
i, err := strconv.ParseInt(strings.Trim(line, "\n"), 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return []int64{}, err
|
|
||||||
}
|
|
||||||
ret = append(ret, i)
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 contains 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntContains checks the src in any int of the target int slice.
|
|
||||||
func IntContains(target []int, src int) bool {
|
|
||||||
for _, t := range target {
|
|
||||||
if src == t {
|
|
||||||
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 retrieves the environment variable key. If it does not exist it returns the default.
|
|
||||||
func GetEnv(key string, dfault string, combineWith ...string) string {
|
|
||||||
value := os.Getenv(key)
|
|
||||||
if value == "" {
|
|
||||||
value = dfault
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(combineWith) {
|
|
||||||
case 0:
|
|
||||||
return value
|
|
||||||
case 1:
|
|
||||||
return filepath.Join(value, combineWith[0])
|
|
||||||
default:
|
|
||||||
all := make([]string, len(combineWith)+1)
|
|
||||||
all[0] = value
|
|
||||||
copy(all[1:], combineWith)
|
|
||||||
return filepath.Join(all...)
|
|
||||||
}
|
|
||||||
panic("invalid switch case")
|
|
||||||
}
|
|
||||||
|
|
||||||
func HostProc(combineWith ...string) string {
|
|
||||||
return GetEnv("HOST_PROC", "/proc", combineWith...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func HostSys(combineWith ...string) string {
|
|
||||||
return GetEnv("HOST_SYS", "/sys", combineWith...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func HostEtc(combineWith ...string) string {
|
|
||||||
return GetEnv("HOST_ETC", "/etc", combineWith...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CombinedOutputTimeout runs the given command with the given timeout and
|
|
||||||
// returns the combined output of stdout and stderr.
|
|
||||||
// If the command times out, it attempts to kill the process.
|
|
||||||
// copied from https://github.com/influxdata/telegraf
|
|
||||||
func CombinedOutputTimeout(c *exec.Cmd, timeout time.Duration) ([]byte, error) {
|
|
||||||
var b bytes.Buffer
|
|
||||||
c.Stdout = &b
|
|
||||||
c.Stderr = &b
|
|
||||||
if err := c.Start(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err := WaitTimeout(c, timeout)
|
|
||||||
return b.Bytes(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitTimeout waits for the given command to finish with a timeout.
|
|
||||||
// It assumes the command has already been started.
|
|
||||||
// If the command times out, it attempts to kill the process.
|
|
||||||
// copied from https://github.com/influxdata/telegraf
|
|
||||||
func WaitTimeout(c *exec.Cmd, timeout time.Duration) error {
|
|
||||||
timer := time.NewTimer(timeout)
|
|
||||||
done := make(chan error)
|
|
||||||
go func() { done <- c.Wait() }()
|
|
||||||
select {
|
|
||||||
case err := <-done:
|
|
||||||
timer.Stop()
|
|
||||||
return err
|
|
||||||
case <-timer.C:
|
|
||||||
if err := c.Process.Kill(); err != nil {
|
|
||||||
log.Printf("FATAL error killing process: %s", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// wait for the command to return after killing it
|
|
||||||
<-done
|
|
||||||
return ErrTimeout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://gist.github.com/kylelemons/1525278
|
|
||||||
func Pipeline(cmds ...*exec.Cmd) ([]byte, []byte, error) {
|
|
||||||
// Require at least one command
|
|
||||||
if len(cmds) < 1 {
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect the output from the command(s)
|
|
||||||
var output bytes.Buffer
|
|
||||||
var stderr bytes.Buffer
|
|
||||||
|
|
||||||
last := len(cmds) - 1
|
|
||||||
for i, cmd := range cmds[:last] {
|
|
||||||
var err error
|
|
||||||
// Connect each command's stdin to the previous command's stdout
|
|
||||||
if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
// Connect each command's stderr to a buffer
|
|
||||||
cmd.Stderr = &stderr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect the output and error for the last command
|
|
||||||
cmds[last].Stdout, cmds[last].Stderr = &output, &stderr
|
|
||||||
|
|
||||||
// Start each command
|
|
||||||
for _, cmd := range cmds {
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return output.Bytes(), stderr.Bytes(), err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for each command to complete
|
|
||||||
for _, cmd := range cmds {
|
|
||||||
if err := cmd.Wait(); err != nil {
|
|
||||||
return output.Bytes(), stderr.Bytes(), err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the pipeline output and the collected standard error
|
|
||||||
return output.Bytes(), stderr.Bytes(), nil
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
// +build darwin
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func DoSysctrl(mib string) ([]string, error) {
|
|
||||||
err := os.Setenv("LC_ALL", "C")
|
|
||||||
if err != nil {
|
|
||||||
return []string{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sysctl, err := exec.LookPath("/usr/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 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
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
// +build freebsd openbsd
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
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 CallSyscall(mib []int32) ([]byte, uint64, error) {
|
|
||||||
mibptr := unsafe.Pointer(&mib[0])
|
|
||||||
miblen := uint64(len(mib))
|
|
||||||
|
|
||||||
// get required buffer size
|
|
||||||
length := uint64(0)
|
|
||||||
_, _, err := syscall.Syscall6(
|
|
||||||
syscall.SYS___SYSCTL,
|
|
||||||
uintptr(mibptr),
|
|
||||||
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(mibptr),
|
|
||||||
uintptr(miblen),
|
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
|
||||||
uintptr(unsafe.Pointer(&length)),
|
|
||||||
0,
|
|
||||||
0)
|
|
||||||
if err != 0 {
|
|
||||||
return buf, length, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf, length, nil
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
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())
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
list, err := f.Readdir(-1)
|
|
||||||
defer f.Close()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return uint64(len(list)), err
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
// +build openbsd
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
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 CallSyscall(mib []int32) ([]byte, uint64, error) {
|
|
||||||
mibptr := unsafe.Pointer(&mib[0])
|
|
||||||
miblen := uint64(len(mib))
|
|
||||||
|
|
||||||
// get required buffer size
|
|
||||||
length := uint64(0)
|
|
||||||
_, _, err := syscall.Syscall6(
|
|
||||||
syscall.SYS___SYSCTL,
|
|
||||||
uintptr(mibptr),
|
|
||||||
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(mibptr),
|
|
||||||
uintptr(miblen),
|
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
|
||||||
uintptr(unsafe.Pointer(&length)),
|
|
||||||
0,
|
|
||||||
0)
|
|
||||||
if err != 0 {
|
|
||||||
return buf, length, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf, length, nil
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
// +build linux freebsd darwin openbsd
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func CallPgrep(invoke Invoker, pid int32) ([]int32, error) {
|
|
||||||
var cmd []string
|
|
||||||
cmd = []string{"-P", strconv.Itoa(int(pid))}
|
|
||||||
pgrep, err := exec.LookPath("pgrep")
|
|
||||||
if err != nil {
|
|
||||||
return []int32{}, err
|
|
||||||
}
|
|
||||||
out, err := invoke.Command(pgrep, cmd...)
|
|
||||||
if err != nil {
|
|
||||||
return []int32{}, err
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(out), "\n")
|
|
||||||
ret := make([]int32, 0, len(lines))
|
|
||||||
for _, l := range lines {
|
|
||||||
if len(l) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i, err := strconv.Atoi(l)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ret = append(ret, int32(i))
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
// +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
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
# This script is a helper of migration to gopsutil v2 using gorename
|
|
||||||
#
|
|
||||||
# go get golang.org/x/tools/cmd/gorename
|
|
||||||
|
|
||||||
IFS=$'\n'
|
|
||||||
|
|
||||||
## Part 1. rename Functions to pass golint. ex) cpu.CPUTimesStat -> cpu.TimesStat
|
|
||||||
|
|
||||||
#
|
|
||||||
# Note:
|
|
||||||
# process has IOCounters() for file IO, and also NetIOCounters() for Net IO.
|
|
||||||
# This scripts replace process.NetIOCounters() to IOCounters().
|
|
||||||
# So you need hand-fixing process.
|
|
||||||
|
|
||||||
TARGETS=`cat <<EOF
|
|
||||||
CPUTimesStat -> TimesStat
|
|
||||||
CPUInfoStat -> InfoStat
|
|
||||||
CPUTimes -> Times
|
|
||||||
CPUInfo -> Info
|
|
||||||
CPUCounts -> Counts
|
|
||||||
CPUPercent -> Percent
|
|
||||||
DiskUsageStat -> UsageStat
|
|
||||||
DiskPartitionStat -> PartitionStat
|
|
||||||
DiskIOCountersStat -> IOCountersStat
|
|
||||||
DiskPartitions -> Partitions
|
|
||||||
DiskIOCounters -> IOCounters
|
|
||||||
DiskUsage -> Usage
|
|
||||||
HostInfoStat -> InfoStat
|
|
||||||
HostInfo -> Info
|
|
||||||
GetVirtualization -> Virtualization
|
|
||||||
GetPlatformInformation -> PlatformInformation
|
|
||||||
LoadAvgStat -> AvgStat
|
|
||||||
LoadAvg -> Avg
|
|
||||||
NetIOCountersStat -> IOCountersStat
|
|
||||||
NetConnectionStat -> ConnectionStat
|
|
||||||
NetProtoCountersStat -> ProtoCountersStat
|
|
||||||
NetInterfaceAddr -> InterfaceAddr
|
|
||||||
NetInterfaceStat -> InterfaceStat
|
|
||||||
NetFilterStat -> FilterStat
|
|
||||||
NetInterfaces -> Interfaces
|
|
||||||
getNetIOCountersAll -> getIOCountersAll
|
|
||||||
NetIOCounters -> IOCounters
|
|
||||||
NetIOCountersByFile -> IOCountersByFile
|
|
||||||
NetProtoCounters -> ProtoCounters
|
|
||||||
NetFilterCounters -> FilterCounters
|
|
||||||
NetConnections -> Connections
|
|
||||||
NetConnectionsPid -> ConnectionsPid
|
|
||||||
Uid -> UID
|
|
||||||
Id -> ID
|
|
||||||
convertCpuTimes -> convertCPUTimes
|
|
||||||
EOF`
|
|
||||||
|
|
||||||
for T in $TARGETS
|
|
||||||
do
|
|
||||||
echo $T
|
|
||||||
gofmt -w -r "$T" ./*.go
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
###### Part 2 rename JSON key name
|
|
||||||
## Google JSOn style
|
|
||||||
## https://google.github.io/styleguide/jsoncstyleguide.xml
|
|
||||||
|
|
||||||
sed -i "" 's/guest_nice/guestNice/g' cpu/*.go
|
|
||||||
sed -i "" 's/vendor_id/vendorId/g' cpu/*.go
|
|
||||||
sed -i "" 's/physical_id/physicalId/g' cpu/*.go
|
|
||||||
sed -i "" 's/model_name/modelName/g' cpu/*.go
|
|
||||||
sed -i "" 's/cache_size/cacheSize/g' cpu/*.go
|
|
||||||
sed -i "" 's/core_id/coreId/g' cpu/*.go
|
|
||||||
|
|
||||||
sed -i "" 's/inodes_total/inodesTotal/g' disk/*.go
|
|
||||||
sed -i "" 's/inodes_used/inodesUsed/g' disk/*.go
|
|
||||||
sed -i "" 's/inodes_free/inodesFree/g' disk/*.go
|
|
||||||
sed -i "" 's/inodes_used_percent/inodesUsedPercent/g' disk/*.go
|
|
||||||
sed -i "" 's/read_count/readCount/g' disk/*.go
|
|
||||||
sed -i "" 's/write_count/writeCount/g' disk/*.go
|
|
||||||
sed -i "" 's/read_bytes/readBytes/g' disk/*.go
|
|
||||||
sed -i "" 's/write_bytes/writeBytes/g' disk/*.go
|
|
||||||
sed -i "" 's/read_time/readTime/g' disk/*.go
|
|
||||||
sed -i "" 's/write_time/writeTime/g' disk/*.go
|
|
||||||
sed -i "" 's/io_time/ioTime/g' disk/*.go
|
|
||||||
sed -i "" 's/serial_number/serialNumber/g' disk/*.go
|
|
||||||
sed -i "" 's/used_percent/usedPercent/g' disk/*.go
|
|
||||||
sed -i "" 's/inodesUsed_percent/inodesUsedPercent/g' disk/*.go
|
|
||||||
|
|
||||||
sed -i "" 's/total_cache/totalCache/g' docker/*.go
|
|
||||||
sed -i "" 's/total_rss_huge/totalRssHuge/g' docker/*.go
|
|
||||||
sed -i "" 's/total_rss/totalRss/g' docker/*.go
|
|
||||||
sed -i "" 's/total_mapped_file/totalMappedFile/g' docker/*.go
|
|
||||||
sed -i "" 's/total_pgpgin/totalPgpgin/g' docker/*.go
|
|
||||||
sed -i "" 's/total_pgpgout/totalPgpgout/g' docker/*.go
|
|
||||||
sed -i "" 's/total_pgfault/totalPgfault/g' docker/*.go
|
|
||||||
sed -i "" 's/total_pgmajfault/totalPgmajfault/g' docker/*.go
|
|
||||||
sed -i "" 's/total_inactive_anon/totalInactiveAnon/g' docker/*.go
|
|
||||||
sed -i "" 's/total_active_anon/totalActiveAnon/g' docker/*.go
|
|
||||||
sed -i "" 's/total_inactive_file/totalInactiveFile/g' docker/*.go
|
|
||||||
sed -i "" 's/total_active_file/totalActiveFile/g' docker/*.go
|
|
||||||
sed -i "" 's/total_unevictable/totalUnevictable/g' docker/*.go
|
|
||||||
sed -i "" 's/mem_usage_in_bytes/memUsageInBytes/g' docker/*.go
|
|
||||||
sed -i "" 's/mem_max_usage_in_bytes/memMaxUsageInBytes/g' docker/*.go
|
|
||||||
sed -i "" 's/memory.limit_in_bytes/memoryLimitInBbytes/g' docker/*.go
|
|
||||||
sed -i "" 's/memory.failcnt/memoryFailcnt/g' docker/*.go
|
|
||||||
sed -i "" 's/mapped_file/mappedFile/g' docker/*.go
|
|
||||||
sed -i "" 's/container_id/containerID/g' docker/*.go
|
|
||||||
sed -i "" 's/rss_huge/rssHuge/g' docker/*.go
|
|
||||||
sed -i "" 's/inactive_anon/inactiveAnon/g' docker/*.go
|
|
||||||
sed -i "" 's/active_anon/activeAnon/g' docker/*.go
|
|
||||||
sed -i "" 's/inactive_file/inactiveFile/g' docker/*.go
|
|
||||||
sed -i "" 's/active_file/activeFile/g' docker/*.go
|
|
||||||
sed -i "" 's/hierarchical_memory_limit/hierarchicalMemoryLimit/g' docker/*.go
|
|
||||||
|
|
||||||
sed -i "" 's/boot_time/bootTime/g' host/*.go
|
|
||||||
sed -i "" 's/platform_family/platformFamily/g' host/*.go
|
|
||||||
sed -i "" 's/platform_version/platformVersion/g' host/*.go
|
|
||||||
sed -i "" 's/virtualization_system/virtualizationSystem/g' host/*.go
|
|
||||||
sed -i "" 's/virtualization_role/virtualizationRole/g' host/*.go
|
|
||||||
|
|
||||||
sed -i "" 's/used_percent/usedPercent/g' mem/*.go
|
|
||||||
|
|
||||||
sed -i "" 's/bytes_sent/bytesSent/g' net/*.go
|
|
||||||
sed -i "" 's/bytes_recv/bytesRecv/g' net/*.go
|
|
||||||
sed -i "" 's/packets_sent/packetsSent/g' net/*.go
|
|
||||||
sed -i "" 's/packets_recv/packetsRecv/g' net/*.go
|
|
||||||
sed -i "" 's/conntrack_count/conntrackCount/g' net/*.go
|
|
||||||
sed -i "" 's/conntrack_max/conntrackMax/g' net/*.go
|
|
||||||
|
|
||||||
sed -i "" 's/read_count/readCount/g' process/*.go
|
|
||||||
sed -i "" 's/write_count/writeCount/g' process/*.go
|
|
||||||
sed -i "" 's/read_bytes/readBytes/g' process/*.go
|
|
||||||
sed -i "" 's/write_bytes/writeBytes/g' process/*.go
|
|
||||||
sed -i "" 's/shared_clean/sharedClean/g' process/*.go
|
|
||||||
sed -i "" 's/shared_dirty/sharedDirty/g' process/*.go
|
|
||||||
sed -i "" 's/private_clean/privateClean/g' process/*.go
|
|
||||||
sed -i "" 's/private_dirty/privateDirty/g' process/*.go
|
|
|
@ -1,36 +0,0 @@
|
||||||
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
|
|
|
@ -220,10 +220,11 @@ The return code is 200 on success.
|
||||||
|
|
||||||
### <a name="agent_maintenance"></a> /v1/agent/maintenance
|
### <a name="agent_maintenance"></a> /v1/agent/maintenance
|
||||||
|
|
||||||
The node maintenance endpoint can place the agent into "maintenance mode".
|
The node maintenance endpoint is hit with a PUT and is used to place the agent
|
||||||
During maintenance mode, the node will be marked as unavailable and will not be
|
into "maintenance mode". During maintenance mode, the node will be marked as
|
||||||
present in DNS or API queries. This API call is idempotent. Maintenance mode is
|
unavailable and will not be present in DNS or API queries. This API call is
|
||||||
persistent and will be automatically restored on agent restart.
|
idempotent. Maintenance mode is persistent and will be automatically restored
|
||||||
|
on agent restart.
|
||||||
|
|
||||||
The `?enable` flag is required. Acceptable values are either `true` (to enter
|
The `?enable` flag is required. Acceptable values are either `true` (to enter
|
||||||
maintenance mode) or `false` (to resume normal operation).
|
maintenance mode) or `false` (to resume normal operation).
|
||||||
|
|
|
@ -206,6 +206,9 @@ will exit with an error at startup.
|
||||||
- Shared credentials file (`~/.aws/credentials` or the path specified by `AWS_SHARED_CREDENTIALS_FILE`)
|
- Shared credentials file (`~/.aws/credentials` or the path specified by `AWS_SHARED_CREDENTIALS_FILE`)
|
||||||
- ECS task role metadata (container-specific).
|
- ECS task role metadata (container-specific).
|
||||||
- EC2 instance role metadata.
|
- EC2 instance role metadata.
|
||||||
|
|
||||||
|
The only required IAM permission is `ec2:DescribeInstances`, and it is recommended you make a dedicated
|
||||||
|
key used only for auto-joining.
|
||||||
|
|
||||||
* <a name="_retry_join_ec2_tag_value"></a><a href="#_retry_join_ec2_tag_value">`-retry-join-ec2-tag-value`
|
* <a name="_retry_join_ec2_tag_value"></a><a href="#_retry_join_ec2_tag_value">`-retry-join-ec2-tag-value`
|
||||||
</a> - The Amazon EC2 instance tag value to filter on.
|
</a> - The Amazon EC2 instance tag value to filter on.
|
||||||
|
|
Loading…
Reference in New Issue