mirror of
https://github.com/ClusterCockpit/cc-metric-collector.git
synced 2024-11-10 04:27:25 +01:00
Add SNMP test tool
This commit is contained in:
parent
668da6ab1b
commit
c396a1254f
@ -24,6 +24,7 @@ This allows to specify
|
||||
- [`http`](./httpReceiver.md): Listen for HTTP Post requests transporting metrics in InfluxDB line protocol
|
||||
- [`ipmi`](./ipmiReceiver.md): Read IPMI sensor readings
|
||||
- [`redfish`](redfishReceiver.md) Use the Redfish (specification) to query thermal and power metrics
|
||||
- [`snmp`](./snmpReceiver.md) Query SNMP endpoints in the network
|
||||
|
||||
## Contributing own receivers
|
||||
|
||||
|
@ -54,3 +54,7 @@ Each network-attached device that should be queried. A target consits of
|
||||
- `unit` can be empty, an OID or a user-given string
|
||||
|
||||
If a OID is used for `name` or `unit`, the receiver will use the returned values to create the output metric. If there are any issues with the returned values, it uses the `OID`.
|
||||
|
||||
## Testing
|
||||
|
||||
For testing an SNMP endpoint and OIDs, you can use [`scripts/snmpReceiverTest`](../scripts/snmpReceiverTest)
|
37
scripts/snmpReceiverTest/README.md
Normal file
37
scripts/snmpReceiverTest/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
# snmpReceiverTest
|
||||
|
||||
This script is a basic implementation of how the SNMPReceiver to test the connection before configuring
|
||||
the collector to get the data periodically.
|
||||
|
||||
It does not support the specification of the `type`, `type-id`, `stype` and `stype-id` but since they are
|
||||
not required to test the functionality, they are left out.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
$ go run snmpReceiverTest -h
|
||||
Usage of snmpReceiverTest:
|
||||
-community string
|
||||
SNMP community (default "public")
|
||||
-hostname string
|
||||
Hostname (default "127.0.0.1")
|
||||
-name string
|
||||
Name of metric or OID
|
||||
-port string
|
||||
Port number (default "161")
|
||||
-timeout string
|
||||
Timeout for SNMP request (default "1s")
|
||||
-unit string
|
||||
Unit of metric or OID
|
||||
-value string
|
||||
Value OID
|
||||
-version string
|
||||
SNMP version (default "2c")
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```sh
|
||||
$ go run scripts/snmpReceiverTest/snmpReceiverTest.go -name serialNumber -value .1.3.6.1.4.1.6574.1.5.2.0 -hostname $IP -community $COMMUNITY
|
||||
Name: serialNumber, Tags: map[type:node], Meta: map[], fields: map[value:18B0PCNXXXXX], Timestamp: 1702050709599311288
|
||||
```
|
167
scripts/snmpReceiverTest/snmpReceiverTest.go
Normal file
167
scripts/snmpReceiverTest/snmpReceiverTest.go
Normal file
@ -0,0 +1,167 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
lp "github.com/ClusterCockpit/cc-metric-collector/pkg/ccMetric"
|
||||
"github.com/gosnmp/gosnmp"
|
||||
)
|
||||
|
||||
func ReadCLI() map[string]string {
|
||||
args := map[string]string{
|
||||
"port": "161",
|
||||
"community": "public",
|
||||
"version": "2c",
|
||||
"hostname": "127.0.0.1",
|
||||
"timeout": "1s",
|
||||
}
|
||||
|
||||
host_cfg := flag.String("hostname", "127.0.0.1", "Hostname")
|
||||
port_cfg := flag.String("port", "161", "Port number")
|
||||
comm_cfg := flag.String("community", "public", "SNMP community")
|
||||
vers_cfg := flag.String("version", "2c", "SNMP version")
|
||||
time_cfg := flag.String("timeout", "1s", "Timeout for SNMP request")
|
||||
|
||||
name_cfg := flag.String("name", "", "Name of metric or OID")
|
||||
value_cfg := flag.String("value", "", "Value OID")
|
||||
unit_cfg := flag.String("unit", "", "Unit of metric or OID")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
args["port"] = *port_cfg
|
||||
args["community"] = *comm_cfg
|
||||
args["hostname"] = *host_cfg
|
||||
args["version"] = *vers_cfg
|
||||
args["timeout"] = *time_cfg
|
||||
|
||||
args["name"] = *name_cfg
|
||||
args["value"] = *value_cfg
|
||||
args["unit"] = *unit_cfg
|
||||
|
||||
if len(args["name"]) == 0 || len(args["value"]) == 0 {
|
||||
fmt.Printf("Required arguments: --name and --value\n")
|
||||
flag.Usage()
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
func validOid(oid string) bool {
|
||||
// Regex from https://github.com/BornToBeRoot/NETworkManager/blob/6805740762bf19b95051c7eaa73cf2b4727733c3/Source/NETworkManager.Utilities/RegexHelper.cs#L88
|
||||
// Match on leading dot added by Thomas Gruber <thomas.gruber@fau.de>
|
||||
match, err := regexp.MatchString(`^[\.]?[012]\.(?:[0-9]|[1-3][0-9])(\.\d+)*$`, oid)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
args := ReadCLI()
|
||||
|
||||
if len(args["name"]) == 0 || len(args["value"]) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
version := gosnmp.Version2c
|
||||
if len(args["version"]) > 0 {
|
||||
switch args["version"] {
|
||||
case "1":
|
||||
version = gosnmp.Version1
|
||||
case "2c":
|
||||
version = gosnmp.Version2c
|
||||
case "3":
|
||||
version = gosnmp.Version3
|
||||
default:
|
||||
fmt.Printf("Invalid SNMP version '%s'\n", args["version"])
|
||||
return
|
||||
}
|
||||
}
|
||||
v, err := strconv.ParseInt(args["port"], 10, 16)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to parse port number '%s'\n", args["port"])
|
||||
return
|
||||
}
|
||||
port := uint16(v)
|
||||
|
||||
t, err := time.ParseDuration(args["timeout"])
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to parse timeout '%s'\n", args["timeout"])
|
||||
return
|
||||
}
|
||||
timeout := t
|
||||
|
||||
params := &gosnmp.GoSNMP{
|
||||
Target: args["hostname"],
|
||||
Port: port,
|
||||
Community: args["community"],
|
||||
Version: version,
|
||||
Timeout: timeout,
|
||||
}
|
||||
err = params.Connect()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to connect to %s:%d : %v\n", params.Target, params.Port, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
oids := make([]string, 0)
|
||||
idx := 0
|
||||
name := gosnmp.SnmpPDU{
|
||||
Value: args["name"],
|
||||
Name: args["name"],
|
||||
}
|
||||
nameidx := -1
|
||||
value := gosnmp.SnmpPDU{
|
||||
Value: nil,
|
||||
Name: args["value"],
|
||||
}
|
||||
valueidx := -1
|
||||
unit := gosnmp.SnmpPDU{
|
||||
Value: args["unit"],
|
||||
Name: args["unit"],
|
||||
}
|
||||
unitidx := -1
|
||||
if validOid(args["name"]) {
|
||||
oids = append(oids, args["name"])
|
||||
nameidx = idx
|
||||
idx++
|
||||
}
|
||||
if validOid(args["value"]) {
|
||||
oids = append(oids, args["value"])
|
||||
valueidx = idx
|
||||
idx++
|
||||
}
|
||||
if len(args["unit"]) > 0 && validOid(args["unit"]) {
|
||||
oids = append(oids, args["unit"])
|
||||
unitidx = idx
|
||||
}
|
||||
result, err := params.Get(oids)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to get data for OIDs [%s] : %v\n", strings.Join(oids, ", "), err.Error())
|
||||
return
|
||||
}
|
||||
if nameidx >= 0 && len(result.Variables) > nameidx {
|
||||
name = result.Variables[nameidx]
|
||||
}
|
||||
if valueidx >= 0 && len(result.Variables) > valueidx {
|
||||
value = result.Variables[valueidx]
|
||||
}
|
||||
if unitidx >= 0 && len(result.Variables) > unitidx {
|
||||
unit = result.Variables[unitidx]
|
||||
}
|
||||
if value.Value != nil {
|
||||
y, err := lp.New(name.Value.(string), map[string]string{"type": "node"}, map[string]string{}, map[string]interface{}{"value": value.Value}, time.Now())
|
||||
if err == nil {
|
||||
if len(unit.Name) > 0 && unit.Value != nil {
|
||||
y.AddMeta("unit", unit.Value.(string))
|
||||
}
|
||||
fmt.Println(y)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user