introduce basic fact collection
This commit is contained in:
21
client/vendor/github.com/zcalusic/sysinfo/LICENSE
generated
vendored
Normal file
21
client/vendor/github.com/zcalusic/sysinfo/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2016 Zlatko Čalušić
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
204
client/vendor/github.com/zcalusic/sysinfo/README.md
generated
vendored
Normal file
204
client/vendor/github.com/zcalusic/sysinfo/README.md
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
# Sysinfo
|
||||
|
||||
[](https://goreportcard.com/report/github.com/zcalusic/sysinfo)
|
||||
[](https://godoc.org/github.com/zcalusic/sysinfo)
|
||||
[](https://github.com/zcalusic/sysinfo/blob/master/LICENSE)
|
||||
[](https://go.dev/)
|
||||
[](https://www.linuxfoundation.org/)
|
||||
|
||||
Package sysinfo is a Go library providing Linux OS / kernel / hardware system information. It's completely standalone,
|
||||
has no dependencies on the host system and doesn't execute external programs. It collects only "inventory type"
|
||||
information, things that don't change often.
|
||||
|
||||
## Code Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/user"
|
||||
|
||||
"github.com/zcalusic/sysinfo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
current, err := user.Current()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if current.Uid != "0" {
|
||||
log.Fatal("requires superuser privilege")
|
||||
}
|
||||
|
||||
var si sysinfo.SysInfo
|
||||
|
||||
si.GetSysInfo()
|
||||
|
||||
data, err := json.MarshalIndent(&si, "", " ")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
```
|
||||
|
||||
## Motivation
|
||||
|
||||
I couldn't find any self-contained library that would provide set of data/features I needed. So another sysinfo was
|
||||
born.
|
||||
|
||||
The purpose of the library is to collect only inventory info. No metrics like CPU usage or load average will be added.
|
||||
The rule of thumb is, if it's changing during the day, every day, it doesn't belong in the library.
|
||||
|
||||
The library should work well on any modern/supported Linux distribution. There are no plans to add support for older
|
||||
unsupported Linux distributions/kernels, to keep the code clean and robust and reduce the maintenance burden.
|
||||
|
||||
## Requirements
|
||||
|
||||
Sysinfo requires:
|
||||
|
||||
- Linux kernel 4.2 or later
|
||||
- access to /sys & /proc Linux virtual file systems
|
||||
- access to various files in /etc, /var, /run FS hierarchy
|
||||
- superuser privileges (to access SMBIOS/DMI table and detect RAM size and properties)
|
||||
|
||||
Sysinfo doesn't require ANY other external utility on the target system, which is its primary strength, IMHO.
|
||||
|
||||
It depends on Linux internals heavily, so there are no plans to support other operating systems.
|
||||
|
||||
## Installation
|
||||
|
||||
Just use go get.
|
||||
|
||||
```
|
||||
go get github.com/zcalusic/sysinfo
|
||||
```
|
||||
|
||||
There's also a very simple utility demonstrating sysinfo library capabilities. Start it (as superuser) to get pretty
|
||||
formatted JSON output of all the info that sysinfo library provides. Due to its simplicity, the source code of the
|
||||
utility also doubles down as an example of how to use the library.
|
||||
|
||||
```
|
||||
go get github.com/zcalusic/sysinfo/cmd/sysinfo
|
||||
```
|
||||
|
||||
--
|
||||
|
||||
Build demo utility in Docker container: https://github.com/mattscilipoti/compile_sysinfo
|
||||
|
||||
## Sample output
|
||||
|
||||
```json
|
||||
{
|
||||
"sysinfo": {
|
||||
"version": "0.9.1",
|
||||
"timestamp": "2016-09-24T13:30:28.369498856+02:00"
|
||||
},
|
||||
"node": {
|
||||
"hostname": "web12",
|
||||
"machineid": "04aa55927ebd390829367c1757b98cac",
|
||||
"timezone": "Europe/Zagreb"
|
||||
},
|
||||
"os": {
|
||||
"name": "CentOS Linux 7 (Core)",
|
||||
"vendor": "centos",
|
||||
"version": "7",
|
||||
"release": "7.2.1511",
|
||||
"architecture": "amd64"
|
||||
},
|
||||
"kernel": {
|
||||
"release": "3.10.0-327.13.1.el7.x86_64",
|
||||
"version": "#1 SMP Thu Mar 31 16:04:38 UTC 2016",
|
||||
"architecture": "x86_64"
|
||||
},
|
||||
"product": {
|
||||
"name": "RH2288H V3",
|
||||
"vendor": "Huawei",
|
||||
"version": "V100R003",
|
||||
"serial": "2103711GEL10F3430658"
|
||||
},
|
||||
"board": {
|
||||
"name": "BC11HGSA0",
|
||||
"vendor": "Huawei",
|
||||
"version": "V100R003",
|
||||
"serial": "033HXVCNG3107624"
|
||||
},
|
||||
"chassis": {
|
||||
"type": 17,
|
||||
"vendor": "Huawei"
|
||||
},
|
||||
"bios": {
|
||||
"vendor": "Insyde Corp.",
|
||||
"version": "3.16",
|
||||
"date": "03/16/2016"
|
||||
},
|
||||
"cpu": {
|
||||
"vendor": "GenuineIntel",
|
||||
"model": "Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz",
|
||||
"speed": 2400,
|
||||
"cache": 20480,
|
||||
"cpus": 1,
|
||||
"cores": 8,
|
||||
"threads": 16
|
||||
},
|
||||
"memory": {
|
||||
"type": "DRAM",
|
||||
"speed": 2133,
|
||||
"size": 65536
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"name": "sda",
|
||||
"driver": "sd",
|
||||
"vendor": "ATA",
|
||||
"model": "ST9500620NS",
|
||||
"serial": "9XF2HZ9K",
|
||||
"size": 500
|
||||
}
|
||||
],
|
||||
"network": [
|
||||
{
|
||||
"name": "enp3s0f1",
|
||||
"driver": "ixgbe",
|
||||
"macaddress": "84:ad:5a:e3:79:71",
|
||||
"port": "fibre",
|
||||
"speed": 10000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Contributors
|
||||
|
||||
Contributors are welcome, just open a new issue / pull request.
|
||||
|
||||
## License
|
||||
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2016 Zlatko Čalušić
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
18
client/vendor/github.com/zcalusic/sysinfo/bios.go
generated
vendored
Normal file
18
client/vendor/github.com/zcalusic/sysinfo/bios.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
// BIOS information.
|
||||
type BIOS struct {
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Date string `json:"date,omitempty"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getBIOSInfo() {
|
||||
si.BIOS.Vendor = slurpFile("/sys/class/dmi/id/bios_vendor")
|
||||
si.BIOS.Version = slurpFile("/sys/class/dmi/id/bios_version")
|
||||
si.BIOS.Date = slurpFile("/sys/class/dmi/id/bios_date")
|
||||
}
|
||||
22
client/vendor/github.com/zcalusic/sysinfo/board.go
generated
vendored
Normal file
22
client/vendor/github.com/zcalusic/sysinfo/board.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
// Board information.
|
||||
type Board struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Serial string `json:"serial,omitempty"`
|
||||
AssetTag string `json:"assettag,omitempty"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getBoardInfo() {
|
||||
si.Board.Name = slurpFile("/sys/class/dmi/id/board_name")
|
||||
si.Board.Vendor = slurpFile("/sys/class/dmi/id/board_vendor")
|
||||
si.Board.Version = slurpFile("/sys/class/dmi/id/board_version")
|
||||
si.Board.Serial = slurpFile("/sys/class/dmi/id/board_serial")
|
||||
si.Board.AssetTag = slurpFile("/sys/class/dmi/id/board_asset_tag")
|
||||
}
|
||||
26
client/vendor/github.com/zcalusic/sysinfo/chassis.go
generated
vendored
Normal file
26
client/vendor/github.com/zcalusic/sysinfo/chassis.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import "strconv"
|
||||
|
||||
// Chassis information.
|
||||
type Chassis struct {
|
||||
Type uint `json:"type,omitempty"`
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Serial string `json:"serial,omitempty"`
|
||||
AssetTag string `json:"assettag,omitempty"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getChassisInfo() {
|
||||
if chtype, err := strconv.ParseUint(slurpFile("/sys/class/dmi/id/chassis_type"), 10, 64); err == nil {
|
||||
si.Chassis.Type = uint(chtype)
|
||||
}
|
||||
si.Chassis.Vendor = slurpFile("/sys/class/dmi/id/chassis_vendor")
|
||||
si.Chassis.Version = slurpFile("/sys/class/dmi/id/chassis_version")
|
||||
si.Chassis.Serial = slurpFile("/sys/class/dmi/id/chassis_serial")
|
||||
si.Chassis.AssetTag = slurpFile("/sys/class/dmi/id/chassis_asset_tag")
|
||||
}
|
||||
85
client/vendor/github.com/zcalusic/sysinfo/cpu.go
generated
vendored
Normal file
85
client/vendor/github.com/zcalusic/sysinfo/cpu.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CPU information.
|
||||
type CPU struct {
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Model string `json:"model,omitempty"`
|
||||
Speed uint `json:"speed,omitempty"` // CPU clock rate in MHz
|
||||
Cache uint `json:"cache,omitempty"` // CPU cache size in KB
|
||||
Cpus uint `json:"cpus,omitempty"` // number of physical CPUs
|
||||
Cores uint `json:"cores,omitempty"` // number of physical CPU cores
|
||||
Threads uint `json:"threads,omitempty"` // number of logical (HT) CPU cores
|
||||
}
|
||||
|
||||
var (
|
||||
reTwoColumns = regexp.MustCompile("\t+: ")
|
||||
reExtraSpace = regexp.MustCompile(" +")
|
||||
reCacheSize = regexp.MustCompile(`^(\d+) KB$`)
|
||||
)
|
||||
|
||||
func (si *SysInfo) getCPUInfo() {
|
||||
si.CPU.Threads = uint(runtime.NumCPU())
|
||||
|
||||
f, err := os.Open("/proc/cpuinfo")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
cpu := make(map[string]bool)
|
||||
core := make(map[string]bool)
|
||||
|
||||
var cpuID string
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
if sl := reTwoColumns.Split(s.Text(), 2); sl != nil {
|
||||
switch sl[0] {
|
||||
case "physical id":
|
||||
cpuID = sl[1]
|
||||
cpu[cpuID] = true
|
||||
case "core id":
|
||||
coreID := fmt.Sprintf("%s/%s", cpuID, sl[1])
|
||||
core[coreID] = true
|
||||
case "vendor_id":
|
||||
if si.CPU.Vendor == "" {
|
||||
si.CPU.Vendor = sl[1]
|
||||
}
|
||||
case "model name":
|
||||
if si.CPU.Model == "" {
|
||||
// CPU model, as reported by /proc/cpuinfo, can be a bit ugly. Clean up...
|
||||
model := reExtraSpace.ReplaceAllLiteralString(sl[1], " ")
|
||||
si.CPU.Model = strings.Replace(model, "- ", "-", 1)
|
||||
}
|
||||
case "cache size":
|
||||
if si.CPU.Cache == 0 {
|
||||
if m := reCacheSize.FindStringSubmatch(sl[1]); m != nil {
|
||||
if cache, err := strconv.ParseUint(m[1], 10, 64); err == nil {
|
||||
si.CPU.Cache = uint(cache)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if s.Err() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
si.CPU.Cpus = uint(len(cpu))
|
||||
si.CPU.Cores = uint(len(core))
|
||||
}
|
||||
27
client/vendor/github.com/zcalusic/sysinfo/cpuid/LICENSE
generated
vendored
Normal file
27
client/vendor/github.com/zcalusic/sysinfo/cpuid/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
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.
|
||||
9
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid.go
generated
vendored
Normal file
9
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright © 2018 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// Package cpuid gives Go programs access to CPUID opcode.
|
||||
package cpuid
|
||||
|
||||
// CPUID returns processor identification and feature information.
|
||||
func CPUID(info *[4]uint32, ax uint32)
|
||||
16
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid_386.s
generated
vendored
Normal file
16
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid_386.s
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
TEXT ·CPUID(SB),$0-8
|
||||
MOVL ax+4(FP), AX
|
||||
CPUID
|
||||
MOVL info+0(FP), DI
|
||||
MOVL AX, 0(DI)
|
||||
MOVL BX, 4(DI)
|
||||
MOVL CX, 8(DI)
|
||||
MOVL DX, 12(DI)
|
||||
RET
|
||||
|
||||
16
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid_amd64.s
generated
vendored
Normal file
16
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
TEXT ·CPUID(SB),$0-12
|
||||
MOVL ax+8(FP), AX
|
||||
CPUID
|
||||
MOVQ info+0(FP), DI
|
||||
MOVL AX, 0(DI)
|
||||
MOVL BX, 4(DI)
|
||||
MOVL CX, 8(DI)
|
||||
MOVL DX, 12(DI)
|
||||
RET
|
||||
|
||||
10
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid_default.s
generated
vendored
Normal file
10
client/vendor/github.com/zcalusic/sysinfo/cpuid/cpuid_default.s
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build !386,!amd64,!gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·CPUID(SB),NOSPLIT,$0-0
|
||||
RET
|
||||
65
client/vendor/github.com/zcalusic/sysinfo/hypervisor.go
generated
vendored
Normal file
65
client/vendor/github.com/zcalusic/sysinfo/hypervisor.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/zcalusic/sysinfo/cpuid"
|
||||
)
|
||||
|
||||
// https://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID
|
||||
var hvmap = map[string]string{
|
||||
"bhyve bhyve ": "bhyve",
|
||||
"KVMKVMKVM": "kvm",
|
||||
"Microsoft Hv": "hyperv",
|
||||
" lrpepyh vr": "parallels",
|
||||
"VMwareVMware": "vmware",
|
||||
"XenVMMXenVMM": "xenhvm",
|
||||
}
|
||||
|
||||
func isHypervisorActive() bool {
|
||||
var info [4]uint32
|
||||
cpuid.CPUID(&info, 0x1)
|
||||
return info[2]&(1<<31) != 0
|
||||
}
|
||||
|
||||
func getHypervisorCpuid(ax uint32) string {
|
||||
var info [4]uint32
|
||||
cpuid.CPUID(&info, ax)
|
||||
return hvmap[strings.TrimRight(string((*[12]byte)(unsafe.Pointer(&info[1]))[:]), "\000")]
|
||||
}
|
||||
|
||||
func (si *SysInfo) getHypervisor() {
|
||||
if !isHypervisorActive() {
|
||||
if hypervisorType := slurpFile("/sys/hypervisor/type"); hypervisorType != "" {
|
||||
if hypervisorType == "xen" {
|
||||
si.Node.Hypervisor = "xenpv"
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// KVM has been caught to move its real signature to this leaf, and put something completely different in the
|
||||
// standard location. So this leaf must be checked first.
|
||||
if hv := getHypervisorCpuid(0x40000100); hv != "" {
|
||||
si.Node.Hypervisor = hv
|
||||
return
|
||||
}
|
||||
|
||||
if hv := getHypervisorCpuid(0x40000000); hv != "" {
|
||||
si.Node.Hypervisor = hv
|
||||
return
|
||||
}
|
||||
|
||||
// getBIOSInfo() must have run first, to detect BIOS vendor
|
||||
if si.BIOS.Vendor == "Bochs" {
|
||||
si.Node.Hypervisor = "bochs"
|
||||
return
|
||||
}
|
||||
|
||||
si.Node.Hypervisor = "unknown"
|
||||
}
|
||||
14
client/vendor/github.com/zcalusic/sysinfo/kernel_darwin.go
generated
vendored
Normal file
14
client/vendor/github.com/zcalusic/sysinfo/kernel_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package sysinfo
|
||||
|
||||
// Kernel information.
|
||||
type Kernel struct {
|
||||
Release string `json:"release,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Architecture string `json:"architecture,omitempty"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getKernelInfo() {
|
||||
}
|
||||
33
client/vendor/github.com/zcalusic/sysinfo/kernel_linux.go
generated
vendored
Normal file
33
client/vendor/github.com/zcalusic/sysinfo/kernel_linux.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Kernel information.
|
||||
type Kernel struct {
|
||||
Release string `json:"release,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Architecture string `json:"architecture,omitempty"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getKernelInfo() {
|
||||
si.Kernel.Release = slurpFile("/proc/sys/kernel/osrelease")
|
||||
si.Kernel.Version = slurpFile("/proc/sys/kernel/version")
|
||||
|
||||
var uname syscall.Utsname
|
||||
if err := syscall.Uname(&uname); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
si.Kernel.Architecture = strings.TrimRight(string((*[65]byte)(unsafe.Pointer(&uname.Machine))[:]), "\000")
|
||||
}
|
||||
121
client/vendor/github.com/zcalusic/sysinfo/memory.go
generated
vendored
Normal file
121
client/vendor/github.com/zcalusic/sysinfo/memory.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Memory information.
|
||||
type Memory struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Speed uint `json:"speed,omitempty"` // RAM data rate in MT/s
|
||||
Size uint `json:"size,omitempty"` // RAM size in MB
|
||||
}
|
||||
|
||||
func word(data []byte, index int) uint16 {
|
||||
return binary.LittleEndian.Uint16(data[index : index+2])
|
||||
}
|
||||
|
||||
func dword(data []byte, index int) uint32 {
|
||||
return binary.LittleEndian.Uint32(data[index : index+4])
|
||||
}
|
||||
|
||||
func qword(data []byte, index int) uint64 {
|
||||
return binary.LittleEndian.Uint64(data[index : index+8])
|
||||
}
|
||||
|
||||
func (si *SysInfo) getMemoryInfo() {
|
||||
dmi, err := os.ReadFile("/sys/firmware/dmi/tables/DMI")
|
||||
if err != nil {
|
||||
// Xen hypervisor
|
||||
if targetKB := slurpFile("/sys/devices/system/xen_memory/xen_memory0/target_kb"); targetKB != "" {
|
||||
si.Memory.Type = "DRAM"
|
||||
size, _ := strconv.ParseUint(targetKB, 10, 64)
|
||||
si.Memory.Size = uint(size) / 1024
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
si.Memory.Size = 0
|
||||
var memSizeAlt uint
|
||||
loop:
|
||||
for p := 0; p < len(dmi)-1; {
|
||||
recType := dmi[p]
|
||||
recLen := dmi[p+1]
|
||||
|
||||
switch recType {
|
||||
case 4:
|
||||
if si.CPU.Speed == 0 {
|
||||
si.CPU.Speed = uint(word(dmi, p+0x16))
|
||||
}
|
||||
case 17:
|
||||
size := uint(word(dmi, p+0x0c))
|
||||
if size == 0 || size == 0xffff || size&0x8000 == 0x8000 {
|
||||
break
|
||||
}
|
||||
if size == 0x7fff {
|
||||
if recLen >= 0x20 {
|
||||
size = uint(dword(dmi, p+0x1c))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
si.Memory.Size += size
|
||||
|
||||
if si.Memory.Type == "" {
|
||||
// SMBIOS Reference Specification Version 3.0.0, page 92
|
||||
memTypes := [...]string{
|
||||
"Other", "Unknown", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM", "ROM", "FLASH",
|
||||
"EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM", "SDRAM", "SGRAM", "RDRAM",
|
||||
"DDR", "DDR2", "DDR2 FB-DIMM", "Reserved", "Reserved", "Reserved", "DDR3",
|
||||
"FBD2", "DDR4", "LPDDR", "LPDDR2", "LPDDR3", "LPDDR4",
|
||||
}
|
||||
|
||||
if index := int(dmi[p+0x12]); index >= 1 && index <= len(memTypes) {
|
||||
si.Memory.Type = memTypes[index-1]
|
||||
}
|
||||
}
|
||||
|
||||
if si.Memory.Speed == 0 && recLen >= 0x17 {
|
||||
if speed := uint(word(dmi, p+0x15)); speed != 0 {
|
||||
si.Memory.Speed = speed
|
||||
}
|
||||
}
|
||||
case 19:
|
||||
start := uint(dword(dmi, p+0x04))
|
||||
end := uint(dword(dmi, p+0x08))
|
||||
if start == 0xffffffff && end == 0xffffffff {
|
||||
if recLen >= 0x1f {
|
||||
start64 := qword(dmi, p+0x0f)
|
||||
end64 := qword(dmi, p+0x17)
|
||||
memSizeAlt += uint((end64 - start64 + 1) / 1048576)
|
||||
}
|
||||
} else {
|
||||
memSizeAlt += (end - start + 1) / 1024
|
||||
}
|
||||
case 127:
|
||||
break loop
|
||||
}
|
||||
|
||||
for p += int(recLen); p < len(dmi)-1; {
|
||||
if bytes.Equal(dmi[p:p+2], []byte{0, 0}) {
|
||||
p += 2
|
||||
break
|
||||
}
|
||||
p++
|
||||
}
|
||||
}
|
||||
|
||||
// Sometimes DMI type 17 has no information, so we fall back to DMI type 19, to at least get the RAM size.
|
||||
if si.Memory.Size == 0 && memSizeAlt > 0 {
|
||||
si.Memory.Type = "DRAM"
|
||||
si.Memory.Size = memSizeAlt
|
||||
}
|
||||
}
|
||||
18
client/vendor/github.com/zcalusic/sysinfo/meta.go
generated
vendored
Normal file
18
client/vendor/github.com/zcalusic/sysinfo/meta.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import "time"
|
||||
|
||||
// Meta information.
|
||||
type Meta struct {
|
||||
Version string `json:"version"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getMetaInfo() {
|
||||
si.Meta.Version = Version
|
||||
si.Meta.Timestamp = time.Now()
|
||||
}
|
||||
146
client/vendor/github.com/zcalusic/sysinfo/network.go
generated
vendored
Normal file
146
client/vendor/github.com/zcalusic/sysinfo/network.go
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// NetworkDevice information.
|
||||
type NetworkDevice struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Driver string `json:"driver,omitempty"`
|
||||
MACAddress string `json:"macaddress,omitempty"`
|
||||
Port string `json:"port,omitempty"`
|
||||
Speed uint `json:"speed,omitempty"` // device max supported speed in Mbps
|
||||
}
|
||||
|
||||
func getPortType(supp uint32) (port string) {
|
||||
for i, p := range [...]string{"tp", "aui", "mii", "fibre", "bnc"} {
|
||||
if supp&(1<<uint(i+7)) > 0 {
|
||||
port += p + "/"
|
||||
}
|
||||
}
|
||||
|
||||
port = strings.TrimRight(port, "/")
|
||||
return
|
||||
}
|
||||
|
||||
func getMaxSpeed(supp uint32) (speed uint) {
|
||||
// Fancy, right?
|
||||
switch {
|
||||
case supp&0x78000000 > 0:
|
||||
speed = 56000
|
||||
case supp&0x07800000 > 0:
|
||||
speed = 40000
|
||||
case supp&0x00600000 > 0:
|
||||
speed = 20000
|
||||
case supp&0x001c1000 > 0:
|
||||
speed = 10000
|
||||
case supp&0x00008000 > 0:
|
||||
speed = 2500
|
||||
case supp&0x00020030 > 0:
|
||||
speed = 1000
|
||||
case supp&0x0000000c > 0:
|
||||
speed = 100
|
||||
case supp&0x00000003 > 0:
|
||||
speed = 10
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getSupported(name string) uint32 {
|
||||
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_IP)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
|
||||
// struct ethtool_cmd from /usr/include/linux/ethtool.h
|
||||
var ethtool struct {
|
||||
Cmd uint32
|
||||
Supported uint32
|
||||
Advertising uint32
|
||||
Speed uint16
|
||||
Duplex uint8
|
||||
Port uint8
|
||||
PhyAddress uint8
|
||||
Transceiver uint8
|
||||
Autoneg uint8
|
||||
MdioSupport uint8
|
||||
Maxtxpkt uint32
|
||||
Maxrxpkt uint32
|
||||
SpeedHi uint16
|
||||
EthTpMdix uint8
|
||||
Reserved2 uint8
|
||||
LpAdvertising uint32
|
||||
Reserved [2]uint32
|
||||
}
|
||||
|
||||
// ETHTOOL_GSET from /usr/include/linux/ethtool.h
|
||||
const GSET = 0x1
|
||||
|
||||
ethtool.Cmd = GSET
|
||||
|
||||
// struct ifreq from /usr/include/linux/if.h
|
||||
var ifr struct {
|
||||
Name [16]byte
|
||||
Data uintptr
|
||||
}
|
||||
|
||||
copy(ifr.Name[:], name+"\000")
|
||||
ifr.Data = uintptr(unsafe.Pointer(ðtool))
|
||||
|
||||
// SIOCETHTOOL from /usr/include/linux/sockios.h
|
||||
const SIOCETHTOOL = 0x8946
|
||||
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(SIOCETHTOOL), uintptr(unsafe.Pointer(&ifr)))
|
||||
if errno == 0 {
|
||||
return ethtool.Supported
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (si *SysInfo) getNetworkInfo() {
|
||||
sysClassNet := "/sys/class/net"
|
||||
devices, err := os.ReadDir(sysClassNet)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
si.Network = make([]NetworkDevice, 0)
|
||||
for _, link := range devices {
|
||||
fullpath := path.Join(sysClassNet, link.Name())
|
||||
dev, err := os.Readlink(fullpath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(dev, "../../devices/virtual/") {
|
||||
continue
|
||||
}
|
||||
|
||||
supp := getSupported(link.Name())
|
||||
|
||||
device := NetworkDevice{
|
||||
Name: link.Name(),
|
||||
MACAddress: slurpFile(path.Join(fullpath, "address")),
|
||||
Port: getPortType(supp),
|
||||
Speed: getMaxSpeed(supp),
|
||||
}
|
||||
|
||||
if driver, err := os.Readlink(path.Join(fullpath, "device", "driver")); err == nil {
|
||||
device.Driver = path.Base(driver)
|
||||
}
|
||||
|
||||
si.Network = append(si.Network, device)
|
||||
}
|
||||
}
|
||||
99
client/vendor/github.com/zcalusic/sysinfo/node.go
generated
vendored
Normal file
99
client/vendor/github.com/zcalusic/sysinfo/node.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Node information.
|
||||
type Node struct {
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
MachineID string `json:"machineid,omitempty"`
|
||||
Hypervisor string `json:"hypervisor,omitempty"`
|
||||
Timezone string `json:"timezone,omitempty"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getHostname() {
|
||||
si.Node.Hostname = slurpFile("/proc/sys/kernel/hostname")
|
||||
}
|
||||
|
||||
func (si *SysInfo) getSetMachineID() {
|
||||
const pathSystemdMachineID = "/etc/machine-id"
|
||||
const pathDbusMachineID = "/var/lib/dbus/machine-id"
|
||||
|
||||
systemdMachineID := slurpFile(pathSystemdMachineID)
|
||||
dbusMachineID := slurpFile(pathDbusMachineID)
|
||||
|
||||
if systemdMachineID != "" && dbusMachineID != "" {
|
||||
// All OK, just return the machine id.
|
||||
if systemdMachineID == dbusMachineID {
|
||||
si.Node.MachineID = systemdMachineID
|
||||
return
|
||||
}
|
||||
|
||||
// They both exist, but they don't match! Copy systemd machine id to DBUS machine id.
|
||||
spewFile(pathDbusMachineID, systemdMachineID, 0444)
|
||||
si.Node.MachineID = systemdMachineID
|
||||
return
|
||||
}
|
||||
|
||||
// Copy DBUS machine id to non-existent systemd machine id.
|
||||
if systemdMachineID == "" && dbusMachineID != "" {
|
||||
spewFile(pathSystemdMachineID, dbusMachineID, 0444)
|
||||
si.Node.MachineID = dbusMachineID
|
||||
return
|
||||
}
|
||||
|
||||
// Copy systemd machine id to non-existent DBUS machine id.
|
||||
if systemdMachineID != "" && dbusMachineID == "" {
|
||||
spewFile(pathDbusMachineID, systemdMachineID, 0444)
|
||||
si.Node.MachineID = systemdMachineID
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (si *SysInfo) getTimezone() {
|
||||
const zoneInfoPrefix = "/usr/share/zoneinfo/"
|
||||
|
||||
if fi, err := os.Lstat("/etc/localtime"); err == nil {
|
||||
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
if tzfile, err := os.Readlink("/etc/localtime"); err == nil {
|
||||
tzfile = strings.TrimPrefix(tzfile, "..")
|
||||
if strings.HasPrefix(tzfile, zoneInfoPrefix) {
|
||||
si.Node.Timezone = strings.TrimPrefix(tzfile, zoneInfoPrefix)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if timezone := slurpFile("/etc/timezone"); timezone != "" {
|
||||
si.Node.Timezone = timezone
|
||||
return
|
||||
}
|
||||
|
||||
if f, err := os.Open("/etc/sysconfig/clock"); err == nil {
|
||||
defer f.Close()
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
if sl := strings.Split(s.Text(), "="); len(sl) == 2 {
|
||||
if sl[0] == "ZONE" {
|
||||
si.Node.Timezone = strings.Trim(sl[1], `"`)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (si *SysInfo) getNodeInfo() {
|
||||
si.getHostname()
|
||||
si.getSetMachineID()
|
||||
si.getHypervisor()
|
||||
si.getTimezone()
|
||||
}
|
||||
101
client/vendor/github.com/zcalusic/sysinfo/os.go
generated
vendored
Normal file
101
client/vendor/github.com/zcalusic/sysinfo/os.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// OS information.
|
||||
type OS struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Release string `json:"release,omitempty"`
|
||||
Architecture string `json:"architecture,omitempty"`
|
||||
}
|
||||
|
||||
var (
|
||||
rePrettyName = regexp.MustCompile(`^PRETTY_NAME=(.*)$`)
|
||||
reID = regexp.MustCompile(`^ID=(.*)$`)
|
||||
reVersionID = regexp.MustCompile(`^VERSION_ID=(.*)$`)
|
||||
reUbuntu = regexp.MustCompile(`[\( ]([\d\.]+)`)
|
||||
reAlma = regexp.MustCompile(`^AlmaLinux release ([\d\.]+)`)
|
||||
reCentOS = regexp.MustCompile(`^CentOS( Linux)? release ([\d\.]+)`)
|
||||
reRocky = regexp.MustCompile(`^Rocky Linux release ([\d\.]+)`)
|
||||
reRedHat = regexp.MustCompile(`[\( ]([\d\.]+)`)
|
||||
)
|
||||
|
||||
func (si *SysInfo) getOSInfo() {
|
||||
// This seems to be the best and most portable way to detect OS architecture (NOT kernel!)
|
||||
if _, err := os.Stat("/lib64/ld-linux-x86-64.so.2"); err == nil {
|
||||
si.OS.Architecture = "amd64"
|
||||
} else if _, err := os.Stat("/lib/ld-linux.so.2"); err == nil {
|
||||
si.OS.Architecture = "i386"
|
||||
}
|
||||
|
||||
f, err := os.Open("/etc/os-release")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
if m := rePrettyName.FindStringSubmatch(s.Text()); m != nil {
|
||||
si.OS.Name = strings.Trim(m[1], `"`)
|
||||
} else if m := reID.FindStringSubmatch(s.Text()); m != nil {
|
||||
si.OS.Vendor = strings.Trim(m[1], `"`)
|
||||
} else if m := reVersionID.FindStringSubmatch(s.Text()); m != nil {
|
||||
si.OS.Version = strings.Trim(m[1], `"`)
|
||||
}
|
||||
}
|
||||
|
||||
switch si.OS.Vendor {
|
||||
case "debian":
|
||||
si.OS.Release = slurpFile("/etc/debian_version")
|
||||
case "ubuntu":
|
||||
if m := reUbuntu.FindStringSubmatch(si.OS.Name); m != nil {
|
||||
si.OS.Release = m[1]
|
||||
}
|
||||
case "almalinux":
|
||||
if release := slurpFile("/etc/almalinux-release"); release != "" {
|
||||
if m := reAlma.FindStringSubmatch(release); m != nil {
|
||||
si.OS.Release = m[1]
|
||||
}
|
||||
}
|
||||
|
||||
si.OS.Version = strings.Split(si.OS.Release, ".")[0]
|
||||
case "centos":
|
||||
if release := slurpFile("/etc/centos-release"); release != "" {
|
||||
if m := reCentOS.FindStringSubmatch(release); m != nil {
|
||||
si.OS.Release = m[2]
|
||||
}
|
||||
}
|
||||
case "rocky":
|
||||
if release := slurpFile("/etc/rocky-release"); release != "" {
|
||||
if m := reRocky.FindStringSubmatch(release); m != nil {
|
||||
si.OS.Release = m[1]
|
||||
}
|
||||
}
|
||||
|
||||
si.OS.Version = strings.Split(si.OS.Release, ".")[0]
|
||||
|
||||
case "rhel":
|
||||
if release := slurpFile("/etc/redhat-release"); release != "" {
|
||||
if m := reRedHat.FindStringSubmatch(release); m != nil {
|
||||
si.OS.Release = m[1]
|
||||
}
|
||||
}
|
||||
if si.OS.Release == "" {
|
||||
if m := reRedHat.FindStringSubmatch(si.OS.Name); m != nil {
|
||||
si.OS.Release = m[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
client/vendor/github.com/zcalusic/sysinfo/product.go
generated
vendored
Normal file
42
client/vendor/github.com/zcalusic/sysinfo/product.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import "github.com/google/uuid"
|
||||
|
||||
// Product information.
|
||||
type Product struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Serial string `json:"serial,omitempty"`
|
||||
UUID uuid.UUID `json:"uuid,omitempty"`
|
||||
SKU string `json:"sku,omitempty"`
|
||||
}
|
||||
|
||||
func (si *SysInfo) getProductInfo() {
|
||||
si.Product.Name = slurpFile("/sys/class/dmi/id/product_name")
|
||||
si.Product.Vendor = slurpFile("/sys/class/dmi/id/sys_vendor")
|
||||
si.Product.Version = slurpFile("/sys/class/dmi/id/product_version")
|
||||
si.Product.Serial = slurpFile("/sys/class/dmi/id/product_serial")
|
||||
si.Product.SKU = slurpFile("/sys/class/dmi/id/product_sku")
|
||||
|
||||
uid, err := uuid.Parse(slurpFile("/sys/class/dmi/id/product_uuid"))
|
||||
if err == nil {
|
||||
si.Product.UUID = uid
|
||||
}
|
||||
|
||||
// try a fallback to device-tree (ex: dmi is not available on ARM devices)
|
||||
// full details: https://www.devicetree.org/specifications/
|
||||
|
||||
// on linux root path is /proc/device-tree (see: https://github.com/torvalds/linux/blob/v5.9/Documentation/ABI/testing/sysfs-firmware-ofw)
|
||||
if si.Product.Name == "" {
|
||||
si.Product.Name = slurpFile("/proc/device-tree/model")
|
||||
}
|
||||
|
||||
if si.Product.Serial == "" {
|
||||
si.Product.Serial = slurpFile("/proc/device-tree/serial-number")
|
||||
}
|
||||
}
|
||||
104
client/vendor/github.com/zcalusic/sysinfo/storage.go
generated
vendored
Normal file
104
client/vendor/github.com/zcalusic/sysinfo/storage.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// StorageDevice information.
|
||||
type StorageDevice struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Driver string `json:"driver,omitempty"`
|
||||
Vendor string `json:"vendor,omitempty"`
|
||||
Model string `json:"model,omitempty"`
|
||||
Serial string `json:"serial,omitempty"`
|
||||
Size uint `json:"size,omitempty"` // device size in GB
|
||||
}
|
||||
|
||||
func getSerial(name, fullpath string) (serial string) {
|
||||
var f *os.File
|
||||
var err error
|
||||
|
||||
// Modern location/format of the udev database.
|
||||
if dev := slurpFile(path.Join(fullpath, "dev")); dev != "" {
|
||||
if f, err = os.Open(path.Join("/run/udev/data", "b"+dev)); err == nil {
|
||||
goto scan
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy location/format of the udev database.
|
||||
if f, err = os.Open(path.Join("/dev/.udev/db", "block:"+name)); err == nil {
|
||||
goto scan
|
||||
}
|
||||
|
||||
// No serial :(
|
||||
return
|
||||
|
||||
scan:
|
||||
defer f.Close()
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
if sl := strings.Split(s.Text(), "="); len(sl) == 2 {
|
||||
if sl[0] == "E:ID_SERIAL_SHORT" {
|
||||
serial = sl[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (si *SysInfo) getStorageInfo() {
|
||||
sysBlock := "/sys/block"
|
||||
devices, err := os.ReadDir(sysBlock)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
si.Storage = make([]StorageDevice, 0)
|
||||
for _, link := range devices {
|
||||
fullpath := path.Join(sysBlock, link.Name())
|
||||
dev, err := os.Readlink(fullpath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(dev, "../devices/virtual/") {
|
||||
continue
|
||||
}
|
||||
|
||||
// We could filter all removable devices here, but some systems boot from USB flash disks, and then we
|
||||
// would filter them, too. So, let's filter only floppies and CD/DVD devices, and see how it pans out.
|
||||
if strings.HasPrefix(dev, "../devices/platform/floppy") || slurpFile(path.Join(fullpath, "device", "type")) == "5" {
|
||||
continue
|
||||
}
|
||||
|
||||
device := StorageDevice{
|
||||
Name: link.Name(),
|
||||
Model: slurpFile(path.Join(fullpath, "device", "model")),
|
||||
Serial: getSerial(link.Name(), fullpath),
|
||||
}
|
||||
|
||||
if driver, err := os.Readlink(path.Join(fullpath, "device", "driver")); err == nil {
|
||||
device.Driver = path.Base(driver)
|
||||
}
|
||||
|
||||
if vendor := slurpFile(path.Join(fullpath, "device", "vendor")); !strings.HasPrefix(vendor, "0x") {
|
||||
device.Vendor = vendor
|
||||
}
|
||||
|
||||
size, _ := strconv.ParseUint(slurpFile(path.Join(fullpath, "size")), 10, 64)
|
||||
device.Size = uint(size) / 1953125 // GiB
|
||||
|
||||
si.Storage = append(si.Storage, device)
|
||||
}
|
||||
}
|
||||
49
client/vendor/github.com/zcalusic/sysinfo/sysinfo.go
generated
vendored
Normal file
49
client/vendor/github.com/zcalusic/sysinfo/sysinfo.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
// Package sysinfo is a Go library providing Linux OS / kernel / hardware system information.
|
||||
package sysinfo
|
||||
|
||||
// SysInfo struct encapsulates all other information structs.
|
||||
type SysInfo struct {
|
||||
Meta Meta `json:"sysinfo"`
|
||||
Node Node `json:"node"`
|
||||
OS OS `json:"os"`
|
||||
Kernel Kernel `json:"kernel"`
|
||||
Product Product `json:"product"`
|
||||
Board Board `json:"board"`
|
||||
Chassis Chassis `json:"chassis"`
|
||||
BIOS BIOS `json:"bios"`
|
||||
CPU CPU `json:"cpu"`
|
||||
Memory Memory `json:"memory"`
|
||||
Storage []StorageDevice `json:"storage,omitempty"`
|
||||
Network []NetworkDevice `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
// GetSysInfo gathers all available system information.
|
||||
func (si *SysInfo) GetSysInfo() {
|
||||
// Meta info
|
||||
si.getMetaInfo()
|
||||
|
||||
// DMI info
|
||||
si.getProductInfo()
|
||||
si.getBoardInfo()
|
||||
si.getChassisInfo()
|
||||
si.getBIOSInfo()
|
||||
|
||||
// SMBIOS info
|
||||
si.getMemoryInfo()
|
||||
|
||||
// Node info
|
||||
si.getNodeInfo() // depends on BIOS info
|
||||
|
||||
// Hardware info
|
||||
si.getCPUInfo() // depends on Node info
|
||||
si.getStorageInfo()
|
||||
si.getNetworkInfo()
|
||||
|
||||
// Software info
|
||||
si.getOSInfo()
|
||||
si.getKernelInfo()
|
||||
}
|
||||
26
client/vendor/github.com/zcalusic/sysinfo/util.go
generated
vendored
Normal file
26
client/vendor/github.com/zcalusic/sysinfo/util.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Read one-liner text files, strip newline.
|
||||
func slurpFile(path string) string {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Trim spaces & \u0000 \uffff
|
||||
return strings.Trim(string(data), " \r\n\t\u0000\uffff")
|
||||
}
|
||||
|
||||
// Write one-liner text files, add newline, ignore errors (best effort).
|
||||
func spewFile(path string, data string, perm os.FileMode) {
|
||||
_ = os.WriteFile(path, []byte(data+"\n"), perm)
|
||||
}
|
||||
8
client/vendor/github.com/zcalusic/sysinfo/version.go
generated
vendored
Normal file
8
client/vendor/github.com/zcalusic/sysinfo/version.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright © 2016 Zlatko Čalušić
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.
|
||||
|
||||
package sysinfo
|
||||
|
||||
// Version of the sysinfo library.
|
||||
const Version = "1.1.3"
|
||||
Reference in New Issue
Block a user