Browse Source

support for availabe space check in bytes

master
Lars Hoogestraat 5 months ago
parent
commit
0d4cc9ae8d
5 changed files with 129 additions and 82 deletions
  1. +1
    -0
      .gitignore
  2. +67
    -41
      README.md
  3. +4
    -1
      go.mod
  4. +7
    -0
      go.sum
  5. +50
    -40
      main.go

+ 1
- 0
.gitignore View File

@ -0,0 +1 @@
.idea/

+ 67
- 41
README.md View File

@ -10,7 +10,7 @@ This tool offers the following abilities:
## Usage
./check_netapp (version|fw|fansfailed|elecfailed|diskfailed)
./check_netapp (version|df|fw|fansfailed|elecfailed|diskfailed)
### Examples
@ -30,25 +30,25 @@ returns the following
SNMPv2-SMI::enterprises.789.1.5.4.1.2.1048 = STRING: "/vol/datastore03"
```
Check the used disk space of volume 1047 (/vol/datastore02)
Returns total / used / available / disk space of volume 1047 (/vol/datastore02)
```
./check_netapp df -H netapp.example.com -C public -i 1047
```
the following text is returned:
returns the following text:
```
Space of volume /vol/datastore02 has usage of 26.54%. Space total: 18.0 TB - Space available: 13.3 TB - Space used: 4.8 TB
```
You can use the name of the volume. It needs to walks over all volumes.
You can use the name of the volume. It needs to walk over all volumes.
```
./check_netapp df -H netapp.example.com -C public -p /vol/datastore02.
```
You can set simple thresholds, -c for critcal (exit code 1) and -w for warnings (exit code 2)
You can set simple thresholds of percentage usage, -c for critical (exit code 1) and -w for warnings (exit code 2)
```
./check_netapp df -H netapp.example.com -C public -i 1047 -c 90 -w 80
@ -56,6 +56,13 @@ You can set simple thresholds, -c for critcal (exit code 1) and -w for warnings
would exit with error code 1, if usage is above 90% and if usage is between 80-90% it returns with exit code 2.
You can set simple thresholds of available space in a string representation, -cb for critical (exit code 1) and -wb for warnings (exit code 2) eg.
```
./check_netapp df -H netapp.example.com -C public -i 1047 -cb '130 MiB' -wb '150 MiB'
./check_netapp df -H netapp.example.com -C public -i 1047 -cb '130 GB' -wb '150 GB'
```
**Fan failures**
Check for failures of the fans
@ -93,6 +100,32 @@ Returns the current firmware information
**Command configuration**
```
object CheckCommand "check-netapp-df" {
command = [ PluginDir + "/check_netapp" ]
arguments = {
"df" = {
order = -1
required = true
}
"-H" = "$address$"
"-i" = "$volumeID$"
"-c" = {
value = "$critical$"
}
"-w" = {
value = "$warning$"
}
"-cb" = {
value = "$criticalBytes$"
}
"-wb" = {
value = "$warningBytes$"
}
}
}
object CheckCommand "check-netapp-electronic" {
command = [ PluginDir + "/check_netapp" ]
@ -143,44 +176,11 @@ object CheckCommand "check-netapp-diskfailed" {
}
```
**Host configuration**
It uses the group "netapp" to apply checks on host.
```
object Host "netapp" {
import "generic-host"
address = "xxx.xxx.xxx.xxx"
display_name = "NetApp
groups += ["netapp"]
vars.volumes["datastore02"] = {
id = 1047
critical = 99
warning = 97
}
}
```
**Service configuration**
```
apply Service "check-netapp-df-" for (identifier => volume in host.vars.volumes) {
import "generic-service"
check_command ="check-netapp-df"
vars.volumeID = volume.id
vars.critical = volume.critical
vars.warning = volume.warning
display_name = identifier
assign where "netapp" in host.groups
}
It uses the group "netapp" to apply the checks.
```
apply Service "check-netapp-version" {
import "generic-service"
@ -228,4 +228,30 @@ apply Service "check-netapp-diskfailed" {
vars.host.name = host.name
assign where "netapp" in host.groups
}
```
```
**Host configuration**
```
object Host "netapp" {
import "generic-host"
address = "xxx.xxx.xxx.xxx"
display_name = "NetApp
groups += ["netapp"]
vars.volumes["datastore01"] = {
id = 1047
criticalBytes = "50 MB"
warningBytes = "100 MB"
}
vars.volumes["datastore02"] = {
id = 1047
critical = 99
warning = 97
}
}
```

+ 4
- 1
go.mod View File

@ -2,4 +2,7 @@ module git.hoogi.eu/snafu/check_netapp
go 1.14
require github.com/gosnmp/gosnmp v1.29.0
require (
github.com/dustin/go-humanize v1.0.0
github.com/gosnmp/gosnmp v1.29.0
)

+ 7
- 0
go.sum View File

@ -1,9 +1,14 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/gosnmp/gosnmp v1.29.0 h1:fEkud7oiYVzR64L+/BQA7uvp+7COI9+XkrUQi8JunYM=
github.com/gosnmp/gosnmp v1.29.0/go.mod h1:Ux0YzU4nV5yDET7dNIijd0VST0BCy8ijBf+gTVFQeaM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -11,5 +16,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 50
- 40
main.go View File

@ -8,12 +8,11 @@ import (
"errors"
"flag"
"fmt"
"math"
"github.com/dustin/go-humanize"
"github.com/gosnmp/gosnmp"
"os"
"strconv"
"strings"
"github.com/gosnmp/gosnmp"
)
type status int
@ -61,17 +60,19 @@ type diskFailedFlags struct {
}
type dfFlags struct {
volumeID int
volume string
listVolumes bool
critical int
warning int
volumeID int
volume string
listVolumes bool
critical int
warning int
criticalBytes string
warningBytes string
}
func usage() {
fmt.Println("check_netapp is a command line tool to check SNMP values from NetApp for e.g. icinga")
fmt.Println("Usage:")
fmt.Println("\t ./check_netapp (version|fw|fansfailed|elecfailed|diskfailed)")
fmt.Println("\t ./check_netapp (version|fw|df|fansfailed|elecfailed|diskfailed)")
}
func main() {
@ -118,6 +119,8 @@ func main() {
df.BoolVar(&dfFlags.listVolumes, "l", false, "List all volumes reported by SNMP")
df.IntVar(&dfFlags.critical, "c", -1, "Percentage of space used before going critical")
df.IntVar(&dfFlags.warning, "w", -1, "Percentage of space used before sending a warning")
df.StringVar(&dfFlags.criticalBytes, "cb", "", "Check available space against a string representation of bytes ('20 MB' / '40 MiB' / '1 GB') before going critical")
df.StringVar(&dfFlags.warningBytes, "wb", "", "Check available space against a string representation of bytes ('20 MB' / '40 MiB' / '1 GB') before sending a warning")
diskFailedFlags := diskFailedFlags{}
@ -515,18 +518,50 @@ func (f dfFlags) diskSpaceUsage() (string, status, error) {
return "", unknown, err
}
hrTotal := humanize.Bytes(iTotal[0] * 1024)
hrAvailable := humanize.Bytes(iAvailable[0] * 1024)
hrUsed := humanize.Bytes(iUsed[0] * 1024)
percentageUsed := 100 / float64(iTotal[0]) * float64(iUsed[0])
if int(percentageUsed) >= f.critical && f.critical > 0 {
return "", critical, fmt.Errorf("Space of volume %s has usage of %.2f%%. Space total: %s - Space available: %s - Space used: %s", strVolName, percentageUsed, hr(iTotal[0]), hr(iAvailable[0]), hr(iUsed[0]))
msg := fmt.Sprintf("Space of volume %s has usage of %.2f%%. Space total: %s - Space available: %s - Space used: %s", strVolName, percentageUsed, hrTotal, hrAvailable, hrUsed)
if f.critical > -1 {
if int(percentageUsed) >= f.critical {
return "", critical, fmt.Errorf(msg, strVolName, percentageUsed, hrTotal, hrAvailable, hrUsed)
}
}
if f.warning > -1 {
if int(percentageUsed) >= f.warning {
return "", warning, errors.New(msg)
}
}
if f.criticalBytes != "" {
criticalBytes, err := humanize.ParseBytes(f.criticalBytes)
if err != nil {
return "", unknown, errors.New(msg)
}
if uint64(iAvailable[0]*1024) <= criticalBytes {
return "", critical, errors.New(msg)
}
}
if int(percentageUsed) >= f.warning && f.warning > 0 {
return "", warning, fmt.Errorf("Space of volume %s has usage of %.2f%%. Space total: %s - Space available: %s - Space used: %s", strVolName, percentageUsed, hr(iTotal[0]), hr(iAvailable[0]), hr(iUsed[0]))
if f.warningBytes != "" {
warningBytes, err := humanize.ParseBytes(f.warningBytes)
if err != nil {
return "", unknown, fmt.Errorf("could not parse bytes from string %s, error: %v", f.warning, err)
}
if uint64(iAvailable[0]*1024) <= warningBytes {
return "", warning, fmt.Errorf(msg, strVolName, percentageUsed, hrTotal, hrAvailable, hrUsed)
}
}
str := fmt.Sprintf("Space of volume %s has usage of %.2f%%. Space total: %s - Space available: %s - Space used: %s", strVolName, percentageUsed, hr(iTotal[0]), hr(iAvailable[0]), hr(iUsed[0]))
return str, ok, nil
return msg, ok, nil
}
func getVolumeID(volName string, in []gosnmp.SnmpPDU) (int, error) {
@ -609,28 +644,3 @@ func getValues(vars []gosnmp.SnmpPDU) ([]interface{}, error) {
return nil, errors.New("unexpected type, object instance with OID %s contained an unknown type")
}
// hr fs input in byte - returns a human readable filesize
func hr(fs uint64) string {
if fs == 0 {
return "0"
}
sizes := []string{"B", "KB", "MB", "GB", "TB"}
exp := math.Floor(math.Log(float64(fs)) / math.Log(1024))
if exp > 4 {
exp = 4
}
s := sizes[int(exp)+1]
if exp == 0 {
return fmt.Sprintf("%d %s", fs, s)
}
val := float64(fs) / float64(math.Pow(1024, exp))
return fmt.Sprintf("%.1f %s", math.Ceil(float64(val)*10)/10, s)
}

Loading…
Cancel
Save