1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2024-12-14 11:57:51 +00:00

Add Match Rules package to be used in Custom Source

- Add a Rule interface to help describe the contract
  between a match rule and the Custom source that uses it.

- Add PciIdRule - a rule that matches on the PCI attributes:
  class, vendor, device. Each is provided as a list of elements(strings).
  Match operation: OR will be performed per element and AND will be
  performed per attribute.
  An empty attribute will not be included in the matching process.
  Example:
  {
    "class": ["0200"]
    "vendor": ["15b3"]
    "device": ["1014", "1016"]
  }

- Add LoadedKmodRule - a rule that matches a list of kernel
  modules with the kernel modules currently loaded in the node.
  Example:
  {
    ["rdma_cm", "ib_core"]
  }
This commit is contained in:
Adrian Chiris 2020-02-16 17:24:06 +02:00
parent 0cfe03012b
commit b9ab93559b
4 changed files with 170 additions and 2 deletions

View file

@ -17,11 +17,10 @@ limitations under the License.
package custom
import (
"encoding/json"
"sigs.k8s.io/node-feature-discovery/source"
)
// Custom Features Configurations
type MatchRule struct {
}

View file

@ -0,0 +1,60 @@
/*
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 rules
import (
"fmt"
"io/ioutil"
"strings"
)
// Rule that matches on loaded kernel modules in the system
type LoadedKModRule []string
const kmodProcfsPath = "/proc/modules"
func (kmods *LoadedKModRule) Match() (bool, error) {
loadedModules, err := kmods.getLoadedModules()
if err != nil {
return false, fmt.Errorf("failed to get loaded kernel modules. %s", err.Error())
}
for _, kmod := range *kmods {
if _, ok := loadedModules[kmod]; !ok {
// kernel module not loaded
return false, nil
}
}
return true, nil
}
func (kmods *LoadedKModRule) getLoadedModules() (map[string]struct{}, error) {
out, err := ioutil.ReadFile(kmodProcfsPath)
if err != nil {
return nil, fmt.Errorf("failed to read file %s: %s", kmodProcfsPath, err.Error())
}
loadedMods := make(map[string]struct{})
for _, line := range strings.Split(string(out), "\n") {
// skip empty lines
if len(line) == 0 {
continue
}
// append loaded module
loadedMods[strings.Fields(line)[0]] = struct{}{}
}
return loadedMods, nil
}

View file

@ -0,0 +1,87 @@
/*
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 rules
import (
"fmt"
pciutils "sigs.k8s.io/node-feature-discovery/source/internal"
)
// Rule that matches on the following PCI device attributes: <class, vendor, device>
// each device attribute will be a list elements(strings).
// Match operation: OR will be performed per element and AND will be performed per attribute.
// An empty attribute will not be included in the matching process.
type PciIdRuleInput struct {
Class []string `json:"class,omitempty"`
Vendor []string `json:"vendor,omitempty"`
Device []string `json:"device,omitempty"`
}
type PciIdRule struct {
PciIdRuleInput
}
// Match PCI devices on the provided list of PCI regular expressions
func (r *PciIdRule) Match() (bool, error) {
devAttr := map[string]bool{}
for _, attr := range []string{"class", "vendor", "device"} {
devAttr[attr] = true
}
allDevs, err := pciutils.DetectPci(devAttr)
if err != nil {
return false, fmt.Errorf("failed to detect PCI devices: %s", err.Error())
}
for _, classDevs := range allDevs {
for _, dev := range classDevs {
// match rule on a single device
if r.matchDevOnRule(dev) {
return true, nil
}
}
}
return false, nil
}
func (r *PciIdRule) matchDevOnRule(dev pciutils.PciDeviceInfo) bool {
if len(r.Class) == 0 && len(r.Vendor) == 0 && len(r.Device) == 0 {
return false
}
if len(r.Class) > 0 && !in(dev["class"], r.Class) {
return false
}
if len(r.Vendor) > 0 && !in(dev["vendor"], r.Vendor) {
return false
}
if len(r.Device) > 0 && !in(dev["device"], r.Device) {
return false
}
return true
}
func in(item string, arr []string) bool {
for _, val := range arr {
if val == item {
return true
}
}
return false
}

View file

@ -0,0 +1,22 @@
/*
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 rules
type Rule interface {
// Match on rule
Match() (bool, error)
}