-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
mib_loader.go
140 lines (122 loc) · 3.18 KB
/
mib_loader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package snmp
import (
"fmt"
"os"
"path/filepath"
"sync"
"github.com/sleepinggenius2/gosmi"
"github.com/influxdata/telegraf"
)
// must init, append path for each directory, load module for every file
// or gosmi will fail without saying why
var m sync.Mutex
var once sync.Once
var cache = make(map[string]bool)
type MibLoader interface {
// appendPath takes the path of a directory
appendPath(path string)
// loadModule takes the name of a file in one of the
// directories. Basename only, no relative or absolute path
loadModule(path string) error
}
type GosmiMibLoader struct{}
func (*GosmiMibLoader) appendPath(path string) {
m.Lock()
defer m.Unlock()
gosmi.AppendPath(path)
}
func (*GosmiMibLoader) loadModule(path string) error {
m.Lock()
defer m.Unlock()
_, err := gosmi.LoadModule(path)
return err
}
// will give all found folders to gosmi and load in all modules found in the folders
func LoadMibsFromPath(paths []string, log telegraf.Logger, loader MibLoader) error {
folders, err := walkPaths(paths, log)
if err != nil {
return err
}
for _, path := range folders {
loader.appendPath(path)
modules, err := os.ReadDir(path)
if err != nil {
log.Warnf("Can't read directory %v", modules)
continue
}
for _, entry := range modules {
info, err := entry.Info()
if err != nil {
log.Warnf("Couldn't get info for %v: %v", entry.Name(), err)
continue
}
if info.Mode()&os.ModeSymlink != 0 {
symlink := filepath.Join(path, info.Name())
target, err := filepath.EvalSymlinks(symlink)
if err != nil {
log.Warnf("Couldn't evaluate symbolic links for %v: %v", symlink, err)
continue
}
//replace symlink's info with the target's info
info, err = os.Lstat(target)
if err != nil {
log.Warnf("Couldn't stat target %v: %v", target, err)
continue
}
}
if info.Mode().IsRegular() {
err := loader.loadModule(info.Name())
if err != nil {
log.Warnf("Couldn't load module %v: %v", info.Name(), err)
continue
}
}
}
}
return nil
}
// should walk the paths given and find all folders
func walkPaths(paths []string, log telegraf.Logger) ([]string, error) {
once.Do(gosmi.Init)
folders := []string{}
for _, mibPath := range paths {
// Check if we loaded that path already and skip it if so
m.Lock()
cached := cache[mibPath]
cache[mibPath] = true
m.Unlock()
if cached {
continue
}
err := filepath.Walk(mibPath, func(path string, info os.FileInfo, err error) error {
if info == nil {
log.Warnf("No mibs found")
if os.IsNotExist(err) {
log.Warnf("MIB path doesn't exist: %q", mibPath)
} else if err != nil {
return err
}
return nil
}
if info.Mode()&os.ModeSymlink != 0 {
target, err := filepath.EvalSymlinks(path)
if err != nil {
log.Warnf("Couldn't evaluate symbolic links for %v: %v", path, err)
}
info, err = os.Lstat(target)
if err != nil {
log.Warnf("Couldn't stat target %v: %v", target, err)
}
path = target
}
if info.IsDir() {
folders = append(folders, path)
}
return nil
})
if err != nil {
return folders, fmt.Errorf("couldn't walk path %q: %w", mibPath, err)
}
}
return folders, nil
}