Skip to content

Commit

Permalink
Merge pull request elastic#1 from vansante/freebsd-no-cgo
Browse files Browse the repository at this point in the history
Make disabled CGO work, replace pkg/errors usage
  • Loading branch information
vansante authored Jan 25, 2024
2 parents 542a34e + 12f913a commit 6a47885
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 171 deletions.
1 change: 1 addition & 0 deletions .ci/scripts/check-cross-compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export CGO_ENABLED=0
GOOS=aix GOARCH=ppc64 go build ./...
GOOS=darwin GOARCH=amd64 go build ./...
GOOS=darwin GOARCH=arm64 go build ./...
GOOS=freebsd GOARCH=amd64 go build ./...
GOOS=linux GOARCH=386 go build ./...
GOOS=linux GOARCH=amd64 go build ./...
GOOS=linux GOARCH=arm go build ./...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@
// specific language governing permissions and limitations
// under the License.

//go:build amd64 || arm64

package freebsd

import (
"fmt"
"syscall"

"github.com/pkg/errors"
)

const hardwareMIB = "hw.machine"

func Architecture() (string, error) {
arch, err := syscall.Sysctl(hardwareMIB)
if err != nil {
return "", errors.Wrap(err, "failed to get architecture")
return "", fmt.Errorf("failed to get architecture: %w", err)
}

return arch, nil
Expand Down
12 changes: 7 additions & 5 deletions providers/freebsd/boottime_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,23 @@
// specific language governing permissions and limitations
// under the License.

//go:build amd64 || arm64

package freebsd

import (
"syscall"
"fmt"
"time"

"github.com/pkg/errors"
"golang.org/x/sys/unix"
)

const kernBoottimeMIB = "kern.boottime"

func BootTime() (time.Time, error) {
var tv syscall.Timeval
if err := sysctlByName(kernBoottimeMIB, &tv); err != nil {
return time.Time{}, errors.Wrap(err, "failed to get host uptime")
tv, err := unix.SysctlTimeval(kernBoottimeMIB)
if err != nil {
return time.Time{}, fmt.Errorf("failed to get host uptime: %w", err)
}

bootTime := time.Unix(int64(tv.Sec), int64(tv.Usec)*int64(time.Microsecond))
Expand Down
2 changes: 0 additions & 2 deletions providers/freebsd/defs_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,3 @@ import "C"
type vmTotal C.struct_vmtotal

type kvmSwap C.struct_kvm_swap

type clockInfo C.struct_clockinfo
76 changes: 56 additions & 20 deletions providers/freebsd/host_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@

package freebsd

// #cgo LDFLAGS: -lkvm
//#include <kvm.h>
//#include <sys/vmmeter.h>
import "C"

import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"

"golang.org/x/sys/unix"

"github.com/joeshaw/multierror"
"github.com/pkg/errors"
"github.com/prometheus/procfs"

"github.com/vansante/go-sysinfo/internal/registry"
Expand Down Expand Up @@ -65,6 +66,10 @@ func (h *host) Info() types.HostInfo {
return h.info
}

func (h *host) FQDN() (string, error) {
return shared.FQDN()
}

func (h *host) CPUTime() (types.CPUTimes, error) {
cpu := types.CPUTimes{}
r := &reader{}
Expand Down Expand Up @@ -100,7 +105,7 @@ type reader struct {

func (r *reader) addErr(err error) bool {
if err != nil {
if errors.Cause(err) != types.ErrNotImplemented {
if errors.Is(err, types.ErrNotImplemented) {
r.errs = append(r.errs, err)
}
return true
Expand Down Expand Up @@ -131,24 +136,21 @@ func (r *reader) cpuTime(cpu *types.CPUTimes) {

func (r *reader) memInfo(m *types.HostMemoryInfo) {
pageSize, err := PageSize()

if r.addErr(err) {
return
}

totalMemory, err := TotalMemory()
m.Total, err = TotalMemory()
if r.addErr(err) {
return
}

m.Total = totalMemory

vm, err := VmTotal()
free, err := FreeMemory()
if r.addErr(err) {
return
}

m.Free = uint64(vm.Free) * uint64(pageSize)
m.Free = uint64(free) * uint64(pageSize)
m.Used = m.Total - m.Free

numFreeBuffers, err := NumFreeBuffers()
Expand All @@ -158,23 +160,24 @@ func (r *reader) memInfo(m *types.HostMemoryInfo) {

m.Available = m.Free + (uint64(numFreeBuffers) * uint64(pageSize))

swap, err := KvmGetSwapInfo()
swapMaxPages, err := SwapMaxPages()
if r.addErr(err) {
return
}

swapMaxPages, err := SwapMaxPages()
swapTotal, err := SwapTotal()
if r.addErr(err) {
return
}

if swap.Total > swapMaxPages {
swap.Total = swapMaxPages
if swapTotal > swapMaxPages {
swapTotal = swapMaxPages
}

m.VirtualTotal = uint64(swap.Total) * uint64(pageSize)
m.VirtualUsed = uint64(swap.Used) * uint64(pageSize)
m.VirtualFree = m.VirtualTotal - m.VirtualUsed
m.VirtualTotal = uint64(swapTotal) * uint64(pageSize)
// TODO: FIXME: Where to get swap used?
//m.VirtualUsed = uint64(swap.Used) * uint64(pageSize)
//m.VirtualFree = m.VirtualTotal - m.VirtualUsed
}

func (r *reader) architecture(h *host) {
Expand Down Expand Up @@ -248,3 +251,36 @@ func (fs *procFS) path(p ...string) string {
elem := append([]string{fs.mountPoint}, p...)
return filepath.Join(elem...)
}

const (
kernCptimeMIB = "kern.cp_time"
kernClockrateMIB = "kern.clockrate"
)

func Cptime() (map[string]uint64, error) {
clock, err := unix.SysctlClockinfo(kernClockrateMIB)
if err != nil {
return make(map[string]uint64), fmt.Errorf("failed to get kern.clockrate: %w", err)
}

cptime, err := syscall.Sysctl(kernCptimeMIB)
if err != nil {
return make(map[string]uint64), fmt.Errorf("failed to get kern.cp_time: %w", err)
}

cpMap := make(map[string]uint64)

times := strings.Split(cptime, " ")
names := [5]string{"User", "Nice", "System", "IRQ", "Idle"}

for index, time := range times {
i, err := strconv.ParseUint(time, 10, 64)
if err != nil {
return cpMap, fmt.Errorf("error parsing kern.cp_time: %w", err)
}

cpMap[names[index]] = i * uint64(clock.Tick) * 1000
}

return cpMap, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@
// specific language governing permissions and limitations
// under the License.

//go:build amd64 || arm64

package freebsd

import (
"syscall"
"fmt"

"github.com/pkg/errors"
"golang.org/x/sys/unix"
)

const kernelReleaseMIB = "kern.osrelease"

func KernelVersion() (string, error) {
version, err := syscall.Sysctl(kernelReleaseMIB)
version, err := unix.Sysctl(kernelReleaseMIB)
if err != nil {
return "", errors.Wrap(err, "failed to get kernel version")
return "", fmt.Errorf("failed to get kernel version: %w", err)
}

return version, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@
// specific language governing permissions and limitations
// under the License.

//go:build amd64 || arm64

package freebsd

import (
"syscall"
"fmt"

"github.com/pkg/errors"
"golang.org/x/sys/unix"
)

const kernelHostUUIDMIB = "kern.hostuuid"

func MachineID() (string, error) {
uuid, err := syscall.Sysctl(kernelHostUUIDMIB)
uuid, err := unix.Sysctl(kernelHostUUIDMIB)
if err != nil {
return "", errors.Wrap(err, "failed to get machine id")
return "", fmt.Errorf("failed to get machine id: %w", err)
}

return uuid, nil
Expand Down
75 changes: 27 additions & 48 deletions providers/freebsd/memory_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,100 +15,79 @@
// specific language governing permissions and limitations
// under the License.

//go:build freebsd && cgo
// +build freebsd,cgo
//go:build freebsd
// +build freebsd

package freebsd

// #cgo LDFLAGS: -lkvm
//#include <sys/cdefs.h>
//#include <sys/types.h>
//#include <sys/sysctl.h>

//#include <paths.h>
//#include <kvm.h>
//#include <stdlib.h>
import "C"

import (
"syscall"
"unsafe"
"fmt"

"github.com/pkg/errors"
"golang.org/x/sys/unix"
)

const (
hwPhysmemMIB = "hw.physmem"
hwPagesizeMIB = "hw.pagesize"
vmVmtotalMIB = "vm.vmtotal"
vmFreeCount = "vm.stats.vm.v_free_count"
vmSwapmaxpagesMIB = "vm.swap_maxpages"
vmSwapTotal = "vm.swap_total"
vfsNumfreebuffersMIB = "vfs.numfreebuffers"
devNull = "/dev/null"
kvmOpen = "kvm_open"
)

func PageSize() (uint32, error) {
var pageSize uint32
if err := sysctlByName(hwPagesizeMIB, &pageSize); err != nil {
return 0, errors.Wrap(err, "failed to get hw.pagesize")
pageSize, err := unix.SysctlUint32(hwPagesizeMIB)
if err != nil {
return 0, fmt.Errorf("failed to get hw.pagesize: %w", err)
}

return pageSize, nil
}

func SwapMaxPages() (uint32, error) {
var maxPages uint32
if err := sysctlByName(hwPhysmemMIB, &maxPages); err != nil {
return 0, errors.Wrap(err, "failed to get vm.swap_maxpages")
maxPages, err := unix.SysctlUint32(vmSwapmaxpagesMIB)
if err != nil {
return 0, fmt.Errorf("failed to get vm.swap_maxpages: %w", err)
}

return maxPages, nil
}

func TotalMemory() (uint64, error) {
var size uint64
if err := sysctlByName(hwPhysmemMIB, &size); err != nil {
return 0, errors.Wrap(err, "failed to get hw.physmem")
size, err := unix.SysctlUint64(hwPhysmemMIB)
if err != nil {
return 0, fmt.Errorf("failed to get hw.physmem: %w", err)
}

return size, nil
}

func VmTotal() (vmTotal, error) {
var vm vmTotal
if err := sysctlByName(vmVmtotalMIB, &vm); err != nil {
return vmTotal{}, errors.Wrap(err, "failed to get vm.vmtotal")
func FreeMemory() (uint32, error) {
free, err := unix.SysctlUint32(vmFreeCount)
if err != nil {
return 0, fmt.Errorf("failed to get vm.stats.vm.v_free_count: %w", err)
}

return vm, nil
return free, nil
}

func NumFreeBuffers() (uint32, error) {
var numfreebuffers uint32
if err := sysctlByName(vfsNumfreebuffersMIB, &numfreebuffers); err != nil {
return 0, errors.Wrap(err, "failed to get vfs.numfreebuffers")
numfreebuffers, err := unix.SysctlUint32(vfsNumfreebuffersMIB)
if err != nil {
return 0, fmt.Errorf("failed to get vfs.numfreebuffers: %w", err)
}

return numfreebuffers, nil
}

func KvmGetSwapInfo() (kvmSwap, error) {
var kdC *C.struct_kvm_t

devNullC := C.CString(devNull)
defer C.free(unsafe.Pointer(devNullC))
kvmOpenC := C.CString(kvmOpen)
defer C.free(unsafe.Pointer(kvmOpenC))

if kdC, err := C.kvm_open(nil, devNullC, nil, syscall.O_RDONLY, kvmOpenC); kdC == nil {
return kvmSwap{}, errors.Wrap(err, "failed to open kvm")
}

defer C.kvm_close((*C.struct___kvm)(unsafe.Pointer(kdC)))

var swap kvmSwap
if n, err := C.kvm_getswapinfo((*C.struct___kvm)(unsafe.Pointer(kdC)), (*C.struct_kvm_swap)(unsafe.Pointer(&swap)), 1, 0); n != 0 {
return kvmSwap{}, errors.Wrap(err, "failed to get kvm_getswapinfo")
func SwapTotal() (uint32, error) {
swap, err := unix.SysctlUint32(vmSwapTotal)
if err != nil {
return 0, fmt.Errorf("failed to get vm.swap_total: %w", err)
}

return swap, nil
Expand Down
Loading

0 comments on commit 6a47885

Please sign in to comment.