-
Notifications
You must be signed in to change notification settings - Fork 2k
/
Copy pathbridge_linux.go
103 lines (86 loc) · 2.64 KB
/
bridge_linux.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
package fingerprint
import (
"bufio"
"fmt"
"os"
"regexp"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/shirou/gopsutil/v3/host"
)
const bridgeKernelModuleName = "bridge"
const (
dynamicModuleRe = `%s\s+.*$`
builtinModuleRe = `.+/%s.ko$`
dependsModuleRe = `.+/%s.ko(\.xz)?:.*$`
)
func (f *BridgeFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintResponse) error {
if err := f.detect(bridgeKernelModuleName); err != nil {
f.logger.Warn("failed to detect bridge kernel module, bridge network mode disabled", "error", err)
return nil
}
resp.NodeResources = &structs.NodeResources{
Networks: []*structs.NetworkResource{{
Mode: "bridge",
}},
NodeNetworks: []*structs.NodeNetworkResource{{
Mode: "bridge",
Device: req.Config.BridgeNetworkName,
}},
}
resp.Detected = true
return nil
}
func (f *BridgeFingerprint) regexp(pattern, module string) *regexp.Regexp {
return regexp.MustCompile(fmt.Sprintf(pattern, module))
}
func (f *BridgeFingerprint) detect(module string) error {
// accumulate errors from every place we might find the module
var errs error
// check if the module has been dynamically loaded
dynamicPath := "/proc/modules"
if err := f.searchFile(module, dynamicPath, f.regexp(dynamicModuleRe, module)); err != nil {
errs = multierror.Append(errs, err)
} else {
return nil
}
// will need kernel info to look for builtin and unloaded modules
hostInfo, err := host.Info()
if err != nil {
return err
}
// check if the module is builtin to the kernel
builtinPath := fmt.Sprintf("/lib/modules/%s/modules.builtin", hostInfo.KernelVersion)
if err := f.searchFile(module, builtinPath, f.regexp(builtinModuleRe, module)); err != nil {
errs = multierror.Append(errs, err)
} else {
return nil
}
// check if the module is dynamic but unloaded (will have a dep entry)
dependsPath := fmt.Sprintf("/lib/modules/%s/modules.dep", hostInfo.KernelVersion)
if err := f.searchFile(module, dependsPath, f.regexp(dependsModuleRe, module)); err != nil {
errs = multierror.Append(errs, err)
} else {
return nil
}
return errs
}
func (f *BridgeFingerprint) searchFile(module, filename string, re *regexp.Regexp) error {
file, err := os.Open(filename)
if err != nil {
return fmt.Errorf("failed to open %s: %v", filename, err)
}
defer func() {
_ = file.Close()
}()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if re.MatchString(scanner.Text()) {
return nil // found the module!
}
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("failed to scan %s: %v", filename, err)
}
return fmt.Errorf("module %s not in %s", module, filename)
}