Skip to content

Commit

Permalink
for debugging, use a walk file to return fake results (#712)
Browse files Browse the repository at this point in the history
  • Loading branch information
i3149 authored Jun 1, 2024
1 parent 408a216 commit da6649e
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 11 deletions.
2 changes: 2 additions & 0 deletions cmd/ktranslate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,8 @@ func applyFlags(cfg *ktranslate.Config) error {
return
}
cfg.SNMPInput.ValidateMIBs = v
case "snmp_walk_file":
cfg.SNMPInput.RunFromWalkFile = val
// pkg/inputs/vpc/gcp
case "gcp.project":
cfg.GCPVPCInput.Enable = true
Expand Down
2 changes: 2 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ type SNMPInputConfig struct {
DiscoveryIntervalMinutes int
DiscoveryOnStart bool
ValidateMIBs bool
RunFromWalkFile string
PollNowTarget string
}

Expand Down Expand Up @@ -491,6 +492,7 @@ func DefaultConfig() *Config {
DiscoveryIntervalMinutes: 0,
DiscoveryOnStart: false,
ValidateMIBs: false,
RunFromWalkFile: "",
},
GCPVPCInput: &GCPVPCInputConfig{
Enable: false,
Expand Down
31 changes: 20 additions & 11 deletions pkg/inputs/snmp/snmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,18 @@ var (
mibdb *mibs.MibDB // Global singleton instance here.
ServiceName = ""

dumpMibTable bool
flowOnly bool
jsonToYaml string
snmpWalk string
snmpWalkOid string
snmpWalkFormat string
snmpOutFile string
snmpPollNow string
snmpDiscoDur int
snmpDiscoSt bool
validateMib bool
dumpMibTable bool
flowOnly bool
jsonToYaml string
snmpWalk string
snmpWalkOid string
snmpWalkFormat string
snmpOutFile string
snmpPollNow string
snmpDiscoDur int
snmpDiscoSt bool
validateMib bool
runFromWalkFile string
)

func init() {
Expand All @@ -55,6 +56,7 @@ func init() {
flag.IntVar(&snmpDiscoDur, "snmp_discovery_min", 0, "If set, run snmp discovery on this interval (in minutes).")
flag.BoolVar(&snmpDiscoSt, "snmp_discovery_on_start", false, "If set, run snmp discovery on application start.")
flag.BoolVar(&validateMib, "snmp_validate", false, "If true, validate mib profiles and exit.")
flag.StringVar(&runFromWalkFile, "snmp_walk_file", "", "If set, use the walk file instead of polling.")
}

func StartSNMPPolls(ctx context.Context, jchfChan chan []*kt.JCHF, metrics *kt.SnmpMetricSet, registry go_metrics.Registry, apic *api.KentikApi, log logger.ContextL, cfg *ktranslate.SNMPInputConfig, resolv *resolv.Resolver, confMgr config.ConfigManager, logchan chan string) error {
Expand All @@ -73,6 +75,13 @@ func StartSNMPPolls(ctx context.Context, jchfChan chan []*kt.JCHF, metrics *kt.S
return snmp_util.DoWalk(v, cfg.WalkOID, cfg.WalkFormat, conf, connectTimeout, retries, log)
}

if v := cfg.RunFromWalkFile; v != "" { // If this flag is set, tell the util function to return responses based only on the walk.
err := snmp_util.LoadFromWalk(ctx, cfg.RunFromWalkFile, log)
if err != nil {
return err
}
}

// Load a mibdb if we have one.
if conf.Global != nil {
mdb, err := mibs.NewMibDB(conf.Global.MibDB, conf.Global.MibProfileDir, cfg.ValidateMIBs, log)
Expand Down
7 changes: 7 additions & 0 deletions pkg/inputs/snmp/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ var (
TRUNCATE = true
NO_TRUNCATE = false
MAX_SNMP_LEN = 128

walkCacheMap map[string]gosnmp.SnmpPDU
)

func ReadOctetString(variable gosnmp.SnmpPDU, truncate bool) (string, bool) {
Expand Down Expand Up @@ -152,6 +154,11 @@ func WalkOID(ctx context.Context, device *kt.SnmpDeviceConfig, oid string, serve
tries = []pollTry{pollTry{walk: walker.WalkAll, sleep: time.Duration(0)}}
} else if device.NoUseBulkWalkAll { // If the device says to not use bulkwalkall, trim this out now.
tries = tries[1:]
} else if len(walkCacheMap) != 0 { // If we are using canned responses.
tries = []pollTry{
pollTry{walk: useCachedMap, sleep: time.Duration(0)},
pollTry{walk: server.BulkWalkAll, sleep: time.Duration(0)},
pollTry{walk: server.WalkAll, sleep: time.Duration(0)}}
}

var err error
Expand Down
73 changes: 73 additions & 0 deletions pkg/inputs/snmp/util/walk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package util

import (
"context"
"fmt"
"os"
"strings"

"github.com/kentik/ktranslate/pkg/eggs/logger"

"github.com/gosnmp/gosnmp"
)

// Load a snmpwalk response from the given file and use it for debugging.
func LoadFromWalk(ctx context.Context, file string, log logger.ContextL) error {
data, err := os.ReadFile(file)
if err != nil {
return err
}

res := map[string]gosnmp.SnmpPDU{}
for _, line := range strings.Split(string(data), "\n") {
pts := strings.SplitN(line, " = ", 2)
if len(pts) != 2 {
continue
}
oid := strings.TrimSpace(pts[0])
if oid[0:1] == "." { // Strip off leading dot.
oid = oid[1:]
}
pp := strings.SplitN(pts[1], ": ", 2)
if len(pp) != 2 {
continue
}
val := pp[1]

switch strings.ToLower(pp[0]) {
case "string":
res[oid] = gosnmp.SnmpPDU{Value: []byte(val), Type: gosnmp.OctetString, Name: oid}
case "integer":
res[oid] = gosnmp.SnmpPDU{Value: val, Type: gosnmp.Integer, Name: oid}
case "counter64":
res[oid] = gosnmp.SnmpPDU{Value: val, Type: gosnmp.Counter64, Name: oid}
case "counter32":
res[oid] = gosnmp.SnmpPDU{Value: val, Type: gosnmp.Counter32, Name: oid}
default:
log.Errorf("Skipping unknown walk type: %s", pp[0])
}
}

walkCacheMap = res
log.Infof("Loaded up %d entries to the walk cache map", len(res))

return nil
}

func useCachedMap(oid string) ([]gosnmp.SnmpPDU, error) {
res := []gosnmp.SnmpPDU{}

if oid[0:1] == "." { // Strip off leading dot.
oid = oid[1:]
}
for k, v := range walkCacheMap {
if strings.HasPrefix(k, oid) {
res = append(res, v)
}
}

if len(res) == 0 {
return nil, fmt.Errorf("Nothing to see")
}
return res, nil
}

0 comments on commit da6649e

Please sign in to comment.