diff --git a/lang/funcs/facts/core/load_darwin.go b/lang/funcs/facts/core/load_darwin.go new file mode 100644 index 00000000..f546c2e5 --- /dev/null +++ b/lang/funcs/facts/core/load_darwin.go @@ -0,0 +1,38 @@ +// Mgmt +// Copyright (C) 2013-2018+ James Shubin and the project contributors +// Written by James Shubin and the project contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// +build darwin + +package core // TODO: should this be in its own individual package? + +/* +#include +*/ +import "C" + +// macOS/Darwin specific implementation to get load. +func load() (one, five, fifteen float64, err error) { + avg := []C.double{0, 0, 0} + + C.getloadavg(&avg[0], C.int(len(avg))) + + one = float64(avg[0]) + five = float64(avg[1]) + fifteen = float64(avg[2]) + + return +} diff --git a/lang/funcs/facts/core/load_posix.go b/lang/funcs/facts/core/load_posix.go new file mode 100644 index 00000000..f80c2d99 --- /dev/null +++ b/lang/funcs/facts/core/load_posix.go @@ -0,0 +1,45 @@ +// Mgmt +// Copyright (C) 2013-2018+ James Shubin and the project contributors +// Written by James Shubin and the project contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// +build !darwin + +package core // TODO: should this be in its own individual package? + +import ( + "syscall" +) + +const ( + // LoadScale factor scales the output from sysinfo to the correct float + // value. + LoadScale = 65536 // XXX: is this correct or should it be 65535? +) + +// load returns the system load averages for the last minute, five minutes and +// fifteen minutes. Calling this more often than once every five seconds seems +// to be unnecessary, since the kernel only updates these values that often. +// TODO: is the kernel update interval configurable? +func load() (one, five, fifteen float64, err error) { + var sysinfo syscall.Sysinfo_t + if err = syscall.Sysinfo(&sysinfo); err != nil { + return + } + one = float64(sysinfo.Loads[0]) / LoadScale + five = float64(sysinfo.Loads[1]) / LoadScale + fifteen = float64(sysinfo.Loads[2]) / LoadScale + return +} diff --git a/lang/funcs/facts/core/loadfact.go b/lang/funcs/facts/core/loadfact.go index a7e8e42e..2402bcee 100644 --- a/lang/funcs/facts/core/loadfact.go +++ b/lang/funcs/facts/core/loadfact.go @@ -18,7 +18,6 @@ package core // TODO: should this be in its own individual package? import ( - "syscall" "time" "github.com/purpleidea/mgmt/lang/funcs/facts" @@ -28,10 +27,6 @@ import ( ) const ( - // LoadScale factor scales the output from sysinfo to the correct float - // value. - LoadScale = 65536 // XXX: is this correct or should it be 65535? - loadSignature = "struct{x1 float; x5 float; x15 float}" ) @@ -114,18 +109,3 @@ func (obj *LoadFact) Close() error { close(obj.closeChan) return nil } - -// load returns the system load averages for the last minute, five minutes and -// fifteen minutes. Calling this more often than once every five seconds seems -// to be unnecessary, since the kernel only updates these values that often. -// TODO: is the kernel update interval configurable? -func load() (one, five, fifteen float64, err error) { - var sysinfo syscall.Sysinfo_t - if err = syscall.Sysinfo(&sysinfo); err != nil { - return - } - one = float64(sysinfo.Loads[0]) / LoadScale - five = float64(sysinfo.Loads[1]) / LoadScale - fifteen = float64(sysinfo.Loads[2]) / LoadScale - return -} diff --git a/test/shell/load0.sh b/test/shell/load0.sh new file mode 100755 index 00000000..df07fa58 --- /dev/null +++ b/test/shell/load0.sh @@ -0,0 +1,48 @@ +#!/bin/bash -e + +if env | grep -q -e '^TRAVIS=true$' && [[ $(uname) == "Darwin" ]]; then + # loadavg glibc calls don't seem to work properly on osx OS in travis + echo "Travis and Jenkins give wonky results here, skipping test!" + exit +fi + +set -o errexit +set -o pipefail + +# Expected load average values eg: load average: 1.64306640625, 1.8076171875, 1.82958984375 +# High precision results are preferred (more than the 2 digits in /proc/loadavg at least). +# Precision varies (eg: 4, 9 or 11 digits). Hence no strict check for precision but +# anything above 3 will do. It is assumed we will hardly ever get a precision lower than 3 digits +# from the current implementations. Otherwise this test would need to be revised. +regex="load average: [0-9]\,[0-9]{3,}, [0-9]\,[0-9]{3,}, [0-9]\,[0-9]{3,}" + +tmpdir="$($mktemp --tmpdir -d tmp.XXX)" + +# macOS workaround https://github.com/purpleidea/mgmt/issues/33 +touch "$tmpdir/loadavg" + +cat > "$tmpdir/load0.mcl" < printf("load average: %f, %f, %f", \$x1, \$x5, \$x15), + state => "exists", +} +EOF + +$timeout --kill-after=30s 15s ./mgmt run --tmp-prefix --converged-timeout=1 --lang "$tmpdir/load0.mcl" & +pid=$! +wait $pid # get exit status +e=$? + +set +e +egrep "$regex" "$tmpdir/loadavg" || fail_test "Could not match $tmpdir/loadavg to '$regex'." + +# cleanup if everything went well +rm -r "$tmpdir" + +exit $e