Browse Source

clean-up / use new gosnmp fork

master
Lars Hoogestraat 5 months ago
parent
commit
0413e95493
5 changed files with 163 additions and 117 deletions
  1. +1
    -5
      README.md
  2. +1
    -1
      THIRDPARTY
  3. +1
    -1
      go.mod
  4. +5
    -8
      go.sum
  5. +155
    -102
      main.go

+ 1
- 5
README.md View File

@ -228,8 +228,4 @@ It uses the group "netapp" to apply checks on host.
vars.host.name = host.name
assign where "netapp" in host.groups
}
```
### Info
* SNMP library from soniah is not maintained since 8th July 2020. [https://github.com/soniah/gosnmp](https://github.com/soniah/gosnmp)
```

+ 1
- 1
THIRDPARTY View File

@ -2,7 +2,7 @@
gosnmp by soniah
Github:
https://github.com/soniah/gosnmp
https://github.com/gosnmp/gosnmp
================================================================================
Copyright 2012-2020 The GoSNMP Authors. All rights reserved. Use of this


+ 1
- 1
go.mod View File

@ -2,4 +2,4 @@ module git.hoogi.eu/snafu/check_netapp
go 1.14
require github.com/soniah/gosnmp v1.27.0
require github.com/gosnmp/gosnmp v1.29.0

+ 5
- 8
go.sum View File

@ -1,18 +1,15 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/soniah/gosnmp v1.27.0 h1:nfmGlwMe/VvpRE5U2Llnt7ytaqT+qIzDzWbm/C75MjQ=
github.com/soniah/gosnmp v1.27.0/go.mod h1:nD71O9B+i/ueeBWp44G03aIY1Y4GJhF/gKK/KyaTzxU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 155
- 102
main.go View File

@ -13,7 +13,7 @@ import (
"strconv"
"strings"
"github.com/soniah/gosnmp"
"github.com/gosnmp/gosnmp"
)
type status int
@ -145,7 +145,7 @@ func main() {
return
}
status, err := dfFlags.diskSpaceUsage()
msg, status, err := dfFlags.diskSpaceUsage()
if err != nil {
fmt.Println(err)
@ -153,6 +153,7 @@ func main() {
return
}
stat = int(status)
fmt.Print(msg)
return
case "version":
version.Parse(os.Args[2:])
@ -165,7 +166,7 @@ func main() {
return
}
status, err := genericFlags.getVersion()
msg, status, err := genericFlags.getVersion()
if err != nil {
fmt.Println(err)
@ -174,6 +175,7 @@ func main() {
}
stat = int(status)
fmt.Print(msg)
return
case "fw":
fw.Parse(os.Args[2:])
@ -186,7 +188,7 @@ func main() {
return
}
status, err := genericFlags.getFirmwareVersion()
msg, status, err := genericFlags.getFirmwareVersion()
if err != nil {
fmt.Println(err)
@ -195,6 +197,7 @@ func main() {
}
stat = int(status)
fmt.Print(msg)
return
case "diskfailed":
diskfailed.Parse(os.Args[2:])
@ -207,7 +210,7 @@ func main() {
return
}
status, err := diskfailedFlags.getDiskFailed()
msg, status, err := diskfailedFlags.getDiskFailed()
if err != nil {
fmt.Println(err)
@ -216,6 +219,7 @@ func main() {
}
stat = int(status)
fmt.Print(msg)
return
case "elecfailed":
elecFailed.Parse(os.Args[2:])
@ -228,7 +232,7 @@ func main() {
return
}
status, err := genericFlags.getElectronicFailed()
msg, status, err := genericFlags.getElectronicFailed()
if err != nil {
fmt.Println(err)
@ -237,6 +241,7 @@ func main() {
}
stat = int(status)
fmt.Print(msg)
return
case "fansfailed":
fansFailed.Parse(os.Args[2:])
@ -248,14 +253,13 @@ func main() {
os.Exit(critical)
}
status, err := genericFlags.getFansFailed()
msg, status, err := genericFlags.getFansFailed()
if err != nil {
fmt.Println(err)
stat = int(status)
return
}
fmt.Print(msg)
stat = int(status)
return
default:
@ -280,126 +284,134 @@ func (f genericFlags) connect() error {
return nil
}
//getVersion returns the version of the NetApp (OID .1.3.6.1.4.1.789.1.1.2.0)
func (f genericFlags) getVersion() (status, error) {
// getVersion returns the product version of the NetApp (OID .1.3.6.1.4.1.789.1.1.2.0)
// http://oidref.com/1.3.6.1.4.1.789.1.1.2.0
func (f genericFlags) getVersion() (string, status, error) {
version, err := gosnmp.Default.Get([]string{productVersion})
if err != nil {
return unknown, fmt.Errorf("Get(%s) err: %v", productVersion, err)
return "", unknown, fmt.Errorf("Get(%s) err: %v", productVersion, err)
}
if err = checkType(version.Variables[0]); err != nil {
return unknown, err
}
str, err := getStringValues(version.Variables)
fmt.Print(version.Variables[0].Value.(string))
if err != nil {
return "", unknown, err
}
return ok, nil
return str[0], ok, nil
}
func (f genericFlags) getElectronicFailed() (status, error) {
// getElectronicFailed the list of failed electronics elements. Valid only if enclElectronicsPresent shows that some are present.
// http://oidref.com/1.3.6.1.4.1.789.1.21.1.2.1.33
func (f genericFlags) getElectronicFailed() (string, status, error) {
elecFailed, err := gosnmp.Default.WalkAll(enclElectronicsFailed)
if err != nil {
return unknown, fmt.Errorf("WalkAll(%s) err: %v", enclElectronicsFailed, err)
return "", unknown, fmt.Errorf("WalkAll(%s) err: %v", enclElectronicsFailed, err)
}
values, err := getStringValues(elecFailed)
if err != nil {
return "", unknown, err
}
elecFailedMsg := ""
for _, v := range elecFailed {
if err = checkType(v); err != nil {
return unknown, err
}
if v.Value.(string) != "" {
elecFailedMsg += fmt.Sprintf("%s\n", v.Value)
for _, str := range values {
if str != "" {
elecFailedMsg += fmt.Sprintf("%s\n", str)
}
}
if elecFailedMsg != "" {
return critical, errors.New(elecFailedMsg)
return "", critical, errors.New(elecFailedMsg)
}
fmt.Print("Electronic is ok")
return ok, nil
return "Electronic is ok", ok, nil
}
func (f genericFlags) getFansFailed() (status, error) {
// getFansFailed the list of failed fans or fan modules in this enclosure. Fans are numbered as described in enclFansPresent.
// http://oidref.com/1.3.6.1.4.1.789.1.21.1.2.1.18
func (f genericFlags) getFansFailed() (string, status, error) {
fansFailed, err := gosnmp.Default.WalkAll(enclFansFailed)
if err != nil {
return unknown, fmt.Errorf("WalkAll(%s) err: %v", enclElectronicsFailed, err)
return "", unknown, fmt.Errorf("WalkAll(%s) err: %v", enclElectronicsFailed, err)
}
fansFailedMsg := ""
for _, v := range fansFailed {
if err = checkType(v); err != nil {
return unknown, err
}
if v.Value.(string) != "" {
fansFailedMsg += fmt.Sprintf("%s\n", v.Value)
values, err := getStringValues(fansFailed)
if err != nil {
return "", unknown, err
}
for _, str := range values {
if str != "" {
fansFailedMsg += fmt.Sprintf("%s\n", str)
}
}
if fansFailedMsg != "" {
return critical, errors.New(fansFailedMsg)
return "", critical, errors.New(fansFailedMsg)
}
fmt.Print("Fans are ok")
return ok, nil
return "Fans are ok", ok, nil
}
//getFirmwareVersion returns the firmware version of the NetApp (OID 1.3.6.1.4.1.789.1.1.6.0)
func (f genericFlags) getFirmwareVersion() (status, error) {
// getFirmwareVersion returns the firmware version of the NetApp
// http://oidref.com/1.3.6.1.4.1.789.1.1.6.0
func (f genericFlags) getFirmwareVersion() (string, status, error) {
version, err := gosnmp.Default.Get([]string{productFirmwareVersion})
if err != nil {
return unknown, fmt.Errorf("Get(%s) err: %v", productFirmwareVersion, err)
return "", unknown, fmt.Errorf("Get(%s) err: %v", productFirmwareVersion, err)
}
err = checkType(version.Variables[0])
str, err := getStringValues(version.Variables)
if err != nil {
return unknown, err
return "", unknown, err
}
fmt.Printf("Firmware version: %s", version.Variables[0].Value)
return ok, nil
return fmt.Sprintf("Firmware version: %s", str[0]), ok, nil
}
//getDiskFailed returns the number of failed disk with the failure message if any
func (f diskfailedFlags) getDiskFailed() (status, error) {
// getDiskFailed returns the number of failed disk with the failure message if any
// http://oidref.com/1.3.6.1.4.1.789.1.6.4.7.0
func (f diskfailedFlags) getDiskFailed() (string, status, error) {
failedDisk, err := gosnmp.Default.Get([]string{diskFailedCount})
if err != nil {
return unknown, fmt.Errorf("Get(%s) err: %v", diskFailedCount, err)
return "", unknown, fmt.Errorf("Get(%s) err: %v", diskFailedCount, err)
}
err = checkType(failedDisk.Variables[0])
str, err := getStringValues(failedDisk.Variables)
if err != nil {
return "", unknown, err
}
iFailedDisk, err := strconv.Atoi(str[0])
if err != nil {
return unknown, err
return "", unknown, err
}
iFailedDisk := failedDisk.Variables[0].Value.(int)
failedDiskMsg, err := f.getDiskFailedMessage(iFailedDisk)
if err != nil {
return unknown, err
return "", unknown, err
}
if f.critical > 0 && iFailedDisk >= f.critical {
return critical, fmt.Errorf(failedDiskMsg)
return "", critical, fmt.Errorf(failedDiskMsg)
} else if f.warning > 0 && iFailedDisk >= f.warning {
return warning, fmt.Errorf(failedDiskMsg)
return "", warning, fmt.Errorf(failedDiskMsg)
}
fmt.Print(failedDiskMsg)
return ok, nil
return failedDiskMsg, ok, nil
}
func (f diskfailedFlags) getDiskFailedMessage(failedDisks int) (string, error) {
@ -412,113 +424,109 @@ func (f diskfailedFlags) getDiskFailedMessage(failedDisks int) (string, error) {
return "", fmt.Errorf("Get(%s) err: %v", diskFailedMessage, err)
}
err = checkType(msg.Variables[0])
str, err := getStringValues(msg.Variables)
if err != nil {
return "", err
}
failedDiskMsg += fmt.Sprintf("\nDescription: %s", msg.Variables[0].Value)
failedDiskMsg += fmt.Sprintf("\nDescription: %s", str[0])
}
return failedDiskMsg, nil
}
//diskSpaceUsage returns the percentage of used space of a volume
func (f dfFlags) diskSpaceUsage() (status, error) {
// diskSpaceUsage returns the percentage of used space of a volume
// http://oidref.com/1.3.6.1.4.1.789.1.5.4.1.2
func (f dfFlags) diskSpaceUsage() (string, status, error) {
volID := f.volumeID
if volID == -1 {
results, err := gosnmp.Default.WalkAll(dfFileSys)
if err != nil {
return unknown, fmt.Errorf("WalkAll(%s): %v", dfFileSys, err)
return "", unknown, fmt.Errorf("WalkAll(%s): %v", dfFileSys, err)
}
if f.listVolumes {
volumes := ""
for _, v := range results {
fmt.Printf("%s %s\n", v.Name, v.Value)
volumes += fmt.Sprintf("%s %s\n", v.Name, v.Value)
}
return ok, nil
return volumes, ok, nil
}
volID, err = getVolumeID(f.volume, results)
if err != nil {
return unknown, err
return "", unknown, err
}
}
volName, err := gosnmp.Default.Get([]string{dfFileSys + "." + strconv.Itoa(volID)})
if err != nil {
return unknown, fmt.Errorf("Get(%s) err: %v", dfFileSys+"."+strconv.Itoa(volID), err)
return "", unknown, fmt.Errorf("Get(%s) err: %v", dfFileSys+"."+strconv.Itoa(volID), err)
}
err = checkType(volName.Variables[0])
strVolName, err := getStringValues(volName.Variables)
if err != nil {
return unknown, err
return "", unknown, err
}
strVolName := volName.Variables[0].Value.(string)
//Get total space
total, err := gosnmp.Default.Get([]string{df64TotalKBytes + "." + strconv.Itoa(volID)})
if err != nil {
return unknown, fmt.Errorf("Get(%s) err: %v", df64TotalKBytes+"."+strconv.Itoa(volID), err)
return "", unknown, fmt.Errorf("Get(%s) err: %v", df64TotalKBytes+"."+strconv.Itoa(volID), err)
}
err = checkType(total.Variables[0])
iTotal, err := getUint64Values(total.Variables)
if err != nil {
return unknown, err
return "", unknown, err
}
//Get used space
used, err := gosnmp.Default.Get([]string{df64UsedKBytes + "." + strconv.Itoa(volID)})
if err != nil {
return unknown, fmt.Errorf("Get(%s) err: %v", df64UsedKBytes+"."+strconv.Itoa(volID), err)
return "", unknown, fmt.Errorf("Get(%s) err: %v", df64UsedKBytes+"."+strconv.Itoa(volID), err)
}
err = checkType(used.Variables[0])
iUsed, err := getUint64Values(used.Variables)
if err != nil {
return unknown, err
return "", unknown, err
}
//Get available space
available, err := gosnmp.Default.Get([]string{df64AvailKBytes + "." + strconv.Itoa(volID)})
if err != nil {
return unknown, fmt.Errorf("Get(%s) err: %v", df64AvailKBytes+"."+strconv.Itoa(volID), err)
return "", unknown, fmt.Errorf("Get(%s) err: %v", df64AvailKBytes+"."+strconv.Itoa(volID), err)
}
err = checkType(available.Variables[0])
iAvailable, err := getUint64Values(available.Variables)
if err != nil {
return unknown, err
return "", unknown, err
}
iused := used.Variables[0].Value.(uint64)
itotal := total.Variables[0].Value.(uint64)
iavailable := available.Variables[0].Value.(uint64)
percUsed := 100 / float64(itotal) * float64(iused)
percentageUsed := 100 / float64(iTotal[0]) * float64(iUsed[0])
if int(percUsed) >= 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, percUsed, hr(itotal), hr(iavailable), hr(iused))
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]))
}
if int(percUsed) >= 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, percUsed, hr(itotal), hr(iavailable), hr(iused))
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]))
}
fmt.Printf("Space of volume %s has usage of %.2f%%. Space total: %s - Space available: %s - Space used: %s", strVolName, percUsed, hr(itotal), hr(iavailable), hr(iused))
return ok, nil
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
}
func getVolumeID(volName string, in []gosnmp.SnmpPDU) (int, error) {
@ -545,16 +553,61 @@ func getVolumeID(volName string, in []gosnmp.SnmpPDU) (int, error) {
return -1, fmt.Errorf("error: volume %s not found", volName)
}
func checkType(pdu gosnmp.SnmpPDU) error {
if pdu.Type == gosnmp.NoSuchInstance {
return fmt.Errorf("no such instance, requested object instance with OID %s could not be returned", pdu.Name)
} else if pdu.Type == gosnmp.NoSuchObject {
return fmt.Errorf("no such object, requested object instance with OID %s could not be returned", pdu.Name)
} else if pdu.Type == gosnmp.UnknownType {
return fmt.Errorf("unknown type, object instance with OID %s contained an unknown type", pdu.Name)
func getStringValues(vars []gosnmp.SnmpPDU) ([]string, error) {
values, err := getValues(vars)
if err != nil {
return nil, err
}
return nil
var str []string
for _, v := range values {
if v2, ok := v.(string); ok {
str = append(str, v2)
}
}
return str, nil
}
func getUint64Values(vars []gosnmp.SnmpPDU) ([]uint64, error) {
values, err := getValues(vars)
if err != nil {
return nil, err
}
var uints []uint64
for _, v := range values {
if v2, ok := v.(uint64); ok {
uints = append(uints, v2)
}
}
return uints, nil
}
func getValues(vars []gosnmp.SnmpPDU) ([]interface{}, error) {
var values []interface{}
for _, variable := range vars {
switch variable.Type {
case gosnmp.OctetString:
values = append(values, string(variable.Value.([]byte)))
case gosnmp.Counter64:
values = append(values, uint64(variable.Value.(uint64)))
case gosnmp.NoSuchInstance:
return nil, fmt.Errorf("no such instance, requested object instance with OID %s could not be returned", variable.Name)
case gosnmp.NoSuchObject:
return nil, fmt.Errorf("no such object, requested object instance with OID %s could not be returned", variable.Name)
case gosnmp.UnknownType:
return nil, fmt.Errorf("unknown type, object instance with OID %s contained an unknown type", variable.Name)
}
return values, nil
}
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


Loading…
Cancel
Save