From e4e3a9f68e533342d4574017c4aaef5b22e1b112 Mon Sep 17 00:00:00 2001 From: Adrian Chiris Date: Sun, 16 Feb 2020 17:33:27 +0200 Subject: [PATCH] Implement the 'custom' feature Source - Implement the 'custom' feature source utilizing the match rules implemented in previous commit. - Add a static custom feature list for: 1. rdma.capable - marks a node where devices that support RDMA are present. 2. rdma.enabled - marks a node where rdma modules have been loaded. A user may extend these features with additional match rules via NFD configuration file. --- source/custom/custom.go | 47 +++++++++++++++++++++++++ source/custom/rules/loaded_kmod_rule.go | 1 + source/custom/rules/pci_id_rule.go | 2 +- source/custom/static_features.go | 46 ++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 source/custom/static_features.go diff --git a/source/custom/custom.go b/source/custom/custom.go index 8497f2aed..300f79a47 100644 --- a/source/custom/custom.go +++ b/source/custom/custom.go @@ -17,11 +17,17 @@ limitations under the License. package custom import ( + "fmt" + "log" + "sigs.k8s.io/node-feature-discovery/source" + "sigs.k8s.io/node-feature-discovery/source/custom/rules" ) // Custom Features Configurations type MatchRule struct { + PciId *rules.PciIdRule `json:"pciId,omitempty""` + LoadedKMod *rules.LoadedKModRule `json:"loadedKMod,omitempty""` } type CustomFeature struct { @@ -42,5 +48,46 @@ func (s Source) Name() string { return "custom" } // Discover features func (s Source) Discover() (source.Features, error) { features := source.Features{} + allFeatureConfig := append(getStaticFeatureConfig(), Config...) + log.Printf("INFO: Custom features: %+v", allFeatureConfig) + // Iterate over features + for _, customFeature := range allFeatureConfig { + featureExist, err := s.discoverFeature(customFeature) + if err != nil { + return features, fmt.Errorf("failed to discover feature: %s. %s", customFeature.Name, err.Error()) + } + if featureExist { + features[customFeature.Name] = true + } + } return features, nil } + +// Process a single feature by Matching on the defined rules. +// A feature is present if all defined Rules in a MatchRule return a match. +func (s Source) discoverFeature(feature CustomFeature) (bool, error) { + for _, rule := range feature.MatchOn { + // PCI ID rule + if rule.PciId != nil { + match, err := rule.PciId.Match() + if err != nil { + return false, err + } + if !match { + continue + } + } + // Loaded kernel module rule + if rule.LoadedKMod != nil { + match, err := rule.LoadedKMod.Match() + if err != nil { + return false, err + } + if !match { + continue + } + } + return true, nil + } + return false, nil +} diff --git a/source/custom/rules/loaded_kmod_rule.go b/source/custom/rules/loaded_kmod_rule.go index 02bcc39be..2bfb8c32f 100644 --- a/source/custom/rules/loaded_kmod_rule.go +++ b/source/custom/rules/loaded_kmod_rule.go @@ -27,6 +27,7 @@ type LoadedKModRule []string const kmodProcfsPath = "/proc/modules" +// Match loaded kernel modules on provided list of kernel modules func (kmods *LoadedKModRule) Match() (bool, error) { loadedModules, err := kmods.getLoadedModules() if err != nil { diff --git a/source/custom/rules/pci_id_rule.go b/source/custom/rules/pci_id_rule.go index ff6cf62f3..45931cddd 100644 --- a/source/custom/rules/pci_id_rule.go +++ b/source/custom/rules/pci_id_rule.go @@ -35,7 +35,7 @@ type PciIdRule struct { PciIdRuleInput } -// Match PCI devices on the provided list of PCI regular expressions +// Match PCI devices on provided PCI device attributes func (r *PciIdRule) Match() (bool, error) { devAttr := map[string]bool{} for _, attr := range []string{"class", "vendor", "device"} { diff --git a/source/custom/static_features.go b/source/custom/static_features.go new file mode 100644 index 000000000..8796380af --- /dev/null +++ b/source/custom/static_features.go @@ -0,0 +1,46 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package custom + +import ( + "sigs.k8s.io/node-feature-discovery/source/custom/rules" +) + +// getStaticFeatures returns statically configured custom features to discover +// e.g RMDA related features. NFD configuration file may extend these custom features by adding rules. +func getStaticFeatureConfig() []CustomFeature { + return []CustomFeature{ + CustomFeature{ + Name: "rdma.capable", + MatchOn: []MatchRule{ + MatchRule{ + PciId: &rules.PciIdRule{ + rules.PciIdRuleInput{Vendor: []string{"15b3"}}, + }, + }, + }, + }, + CustomFeature{ + Name: "rdma.available", + MatchOn: []MatchRule{ + MatchRule{ + LoadedKMod: &rules.LoadedKModRule{"ib_uverbs", "rdma_ucm"}, + }, + }, + }, + } +}