github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/client/fingerprint/bridge_linux.go (about) 1 package fingerprint 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "regexp" 8 9 "github.com/hashicorp/go-multierror" 10 "github.com/hashicorp/nomad/nomad/structs" 11 "github.com/shirou/gopsutil/host" 12 ) 13 14 const bridgeKernelModuleName = "bridge" 15 16 const ( 17 dynamicModuleRe = `%s\s+.*$` 18 builtinModuleRe = `.+/%s.ko$` 19 dependsModuleRe = `.+/%s.ko(\.xz)?:.*$` 20 ) 21 22 func (f *BridgeFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintResponse) error { 23 if err := f.detect(bridgeKernelModuleName); err != nil { 24 f.logger.Warn("failed to detect bridge kernel module, bridge network mode disabled", "error", err) 25 return nil 26 } 27 28 resp.NodeResources = &structs.NodeResources{ 29 Networks: []*structs.NetworkResource{{ 30 Mode: "bridge", 31 }}, 32 NodeNetworks: []*structs.NodeNetworkResource{{ 33 Mode: "bridge", 34 Device: req.Config.BridgeNetworkName, 35 }}, 36 } 37 38 resp.Detected = true 39 return nil 40 } 41 42 func (f *BridgeFingerprint) regexp(pattern, module string) *regexp.Regexp { 43 return regexp.MustCompile(fmt.Sprintf(pattern, module)) 44 } 45 46 func (f *BridgeFingerprint) detect(module string) error { 47 // accumulate errors from every place we might find the module 48 var errs error 49 50 // check if the module has been dynamically loaded 51 dynamicPath := "/proc/modules" 52 if err := f.searchFile(module, dynamicPath, f.regexp(dynamicModuleRe, module)); err != nil { 53 errs = multierror.Append(errs, err) 54 } else { 55 return nil 56 } 57 58 // will need kernel info to look for builtin and unloaded modules 59 hostInfo, err := host.Info() 60 if err != nil { 61 return err 62 } 63 64 // check if the module is builtin to the kernel 65 builtinPath := fmt.Sprintf("/lib/modules/%s/modules.builtin", hostInfo.KernelVersion) 66 if err := f.searchFile(module, builtinPath, f.regexp(builtinModuleRe, module)); err != nil { 67 errs = multierror.Append(errs, err) 68 } else { 69 return nil 70 } 71 72 // check if the module is dynamic but unloaded (will have a dep entry) 73 dependsPath := fmt.Sprintf("/lib/modules/%s/modules.dep", hostInfo.KernelVersion) 74 if err := f.searchFile(module, dependsPath, f.regexp(dependsModuleRe, module)); err != nil { 75 errs = multierror.Append(errs, err) 76 } else { 77 return nil 78 } 79 80 return errs 81 } 82 83 func (f *BridgeFingerprint) searchFile(module, filename string, re *regexp.Regexp) error { 84 file, err := os.Open(filename) 85 if err != nil { 86 return fmt.Errorf("failed to open %s: %v", filename, err) 87 } 88 defer func() { 89 _ = file.Close() 90 }() 91 92 scanner := bufio.NewScanner(file) 93 for scanner.Scan() { 94 if re.MatchString(scanner.Text()) { 95 return nil // found the module! 96 } 97 } 98 if err := scanner.Err(); err != nil { 99 return fmt.Errorf("failed to scan %s: %v", filename, err) 100 } 101 102 return fmt.Errorf("module %s not in %s", module, filename) 103 }