Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable passing input file, output file, and mibs dir on command line … #1028

Merged
merged 7 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 13 additions & 2 deletions generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ make generator mibs
```
## Preparation

It is recommended to have a directory per device family which contains the mibs dir for the device family,
It is recommended to have a directory per device family which contains the mibs dir for the device family,
a logical link to the generator executable and the generator.yml configuration file. This is to avoid name space collisions
in the MIB definition. Keep only the required MIBS in the mibs directory for the devices.
Then merge all the resulting snmp.yml files into one main file that will be used by the snmp_exporter collector.
Expand All @@ -35,6 +35,17 @@ by the snmp_exporter executable to collect data from the snmp enabled devices.

Additional command are available for debugging, use the `help` command to see them.

After building, you can pass a directories of mibs, a path to the `generator.yml`
file and the intended path of your output file e.g. `snmp.yml` to the `generate`
command like so,
```bash
./generator generate \
-m /tmp/deviceFamilyMibs \
-m /tmp/sharedMibs \
-g /tmp/generator.yml \
-o /tmp/snmp.yml
```

### MIB Parsing options

The parsing of MIBs can be controlled using the `--snmp.mibopts` flag. The available values depend on the net-snmp version used to build the generator.
Expand Down Expand Up @@ -173,7 +184,7 @@ modules:
# If one of the target OIDs is used in a lookup, the filter will apply ALL tables using this lookup
# For a network switch, this could be used to collect a subset of interfaces such as uplinks
# For a router, this could be used to collect all real ports but not vlans and other virtual interfaces
# Specifying ifAlias or ifName if they are used in lookups with ifIndex will apply to the filter to
# Specifying ifAlias or ifName if they are used in lookups with ifIndex will apply to the filter to
# all the OIDs that depend on the lookup, such as ifSpeed, ifInHcOctets, etc.
# This feature applies to any table(s) OIDs using a common index
- targets:
Expand Down
6 changes: 4 additions & 2 deletions generator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func generateConfig(nodes *Node, nameToNode map[string]*Node, logger log.Logger)
return fmt.Errorf("unable to determine absolute path for output")
}

content, err := os.ReadFile("generator.yml")
content, err := os.ReadFile(*generatorYmlPath)
if err != nil {
return fmt.Errorf("error reading yml config: %s", err)
}
Expand Down Expand Up @@ -98,7 +98,9 @@ var (
failOnParseErrors = kingpin.Flag("fail-on-parse-errors", "Exit with a non-zero status if there are MIB parsing errors").Default("false").Bool()
snmpMIBOpts = kingpin.Flag("snmp.mibopts", "Toggle various defaults controlling MIB parsing, see snmpwalk --help").String()
generateCommand = kingpin.Command("generate", "Generate snmp.yml from generator.yml")
outputPath = generateCommand.Flag("output-path", "Path to to write resulting config file").Default("snmp.yml").Short('o').String()
userMibsDir = generateCommand.Flag("mibs-dir", "Paths to mibs directory").Default("").Short('m').Strings()
generatorYmlPath = generateCommand.Flag("generator-path", "Path to the input generator.yml file").Default("generator.yml").Short('g').String()
outputPath = generateCommand.Flag("output-path", "Path to write the snmp_exporter's config file").Default("snmp.yml").Short('o').String()
parseErrorsCommand = kingpin.Command("parse_errors", "Debug: Print the parse errors output by NetSNMP")
dumpCommand = kingpin.Command("dump", "Debug: Dump the parsed and prepared MIBs")
)
Expand Down
21 changes: 17 additions & 4 deletions generator/net_snmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import (
"io"
"os"
"sort"
"strings"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
Expand Down Expand Up @@ -152,20 +153,32 @@ var (
}
)

// getMibsDir joins the user-specified MIB directories into a single string; if the user didn't pass any,
// the default netsnmp mibs directory is returned.
func getMibsDir(paths []string) string {
if len(paths) == 1 && paths[0] == "" {
return C.GoString(C.netsnmp_get_mib_directory())
}
return strings.Join(paths, ":")
}

// Initialize NetSNMP. Returns MIB parse errors.
//
// Warning: This function plays with the stderr file descriptor.
func initSNMP(logger log.Logger) (string, error) {
// Load all the MIBs.
os.Setenv("MIBS", "ALL")
// Help the user find their MIB directories.
level.Info(logger).Log("msg", "Loading MIBs", "from", C.GoString(C.netsnmp_get_mib_directory()))
err := os.Setenv("MIBS", "ALL")
if err != nil {
return "", err
}
mibsDir := getMibsDir(*userMibsDir)
level.Info(logger).Log("msg", "Loading MIBs", "from", mibsDir)
C.netsnmp_set_mib_directory(C.CString(mibsDir))
if *snmpMIBOpts != "" {
C.snmp_mib_toggle_options(C.CString(*snmpMIBOpts))
}
// We want the descriptions.
C.snmp_set_save_descriptions(1)

// Make stderr go to a pipe, as netsnmp tends to spew a
// lot of errors on startup that there's no apparent
// way to disable or redirect.
Expand Down