mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-28 18:57:10 +00:00
Implement kernel config detection
This implementation only detects kconfig options ("NO_HZ", "NO_HZ_IDLE", "NO_HZ_FULL" and "PREEMPT"). The corresponding node labels will be node.alpha.kubernetes-incubator.io/nfd-kernel-config.<option name> Currently, only bool and tristate (i.e. '=y' or '=m') kernel config options are supported. Other kconfig types (e.g. string or int) are simply ignored. If the kconfig flag is set to '=y' or '=m', the corresponding node label will be present and it's value will be 'true'.
This commit is contained in:
parent
607e95f290
commit
ce129aef88
4 changed files with 113 additions and 8 deletions
17
README.md
17
README.md
|
@ -116,6 +116,7 @@ the only label value published for features is the string `"true"`._
|
|||
"feature.node.kubernetes.io/node-feature-discovery.version": "v0.3.0",
|
||||
"feature.node.kubernetes.io/nfd-cpuid-<feature-name>": "true",
|
||||
"feature.node.kubernetes.io/nfd-iommu-<feature-name>": "true",
|
||||
"feature.node.kubernetes.io/kernel-config.<option-name>": "true",
|
||||
"feature.node.kubernetes.io/nfd-kernel-version.<version component>": "<version number>",
|
||||
"feature.node.kubernetes.io/nfd-memory-<feature-name>": "true",
|
||||
"feature.node.kubernetes.io/nfd-network-<feature-name>": "true",
|
||||
|
@ -171,12 +172,16 @@ such as restricting discovered features with the --label-whitelist option._
|
|||
|
||||
### Kernel Features
|
||||
|
||||
| Feature | Attribute | Description |
|
||||
| ------- | --------- | ------------------------------------------------------ |
|
||||
| version | full | Full kernel version as reported by `/proc/sys/kernel/osrelease` (e.g. '4.5.6-7-g123abcde')
|
||||
| <br> | major | First component of the kernel version (e.g. '4')
|
||||
| <br> | minor | Second component of the kernel version (e.g. '5')
|
||||
| <br> | revision | Third component of the kernel version (e.g. '6')
|
||||
| Feature | Attribute | Description |
|
||||
| ------- | ----------- | ---------------------------------------------------- |
|
||||
| config | NO_HZ | Kernel config option is enabled
|
||||
| <br> | NO_HZ_FULL |
|
||||
| <br> | NO_HZ_IDLE |
|
||||
| <br> | PREEMPT |
|
||||
| version | full | Full kernel version as reported by `/proc/sys/kernel/osrelease` (e.g. '4.5.6-7-g123abcde')
|
||||
| <br> | major | First component of the kernel version (e.g. '4')
|
||||
| <br> | minor | Second component of the kernel version (e.g. '5')
|
||||
| <br> | revision | Third component of the kernel version (e.g. '6')
|
||||
|
||||
### Local (User-specific Features)
|
||||
|
||||
|
|
|
@ -26,9 +26,15 @@ spec:
|
|||
args:
|
||||
- "--sleep-interval=60s"
|
||||
volumeMounts:
|
||||
- name: host-boot
|
||||
mountPath: "/host-boot"
|
||||
readOnly: true
|
||||
- name: host-sys
|
||||
mountPath: "/host-sys"
|
||||
volumes:
|
||||
- name: host-boot
|
||||
hostPath:
|
||||
path: "/boot"
|
||||
- name: host-sys
|
||||
hostPath:
|
||||
path: "/sys"
|
||||
|
|
|
@ -28,10 +28,16 @@ spec:
|
|||
- containerPort: 7156
|
||||
hostPort: 7156
|
||||
volumeMounts:
|
||||
- name: host-boot
|
||||
mountPath: "/host-boot"
|
||||
readOnly: true
|
||||
- name: host-sys
|
||||
mountPath: "/host-sys"
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: host-boot
|
||||
hostPath:
|
||||
path: "/boot"
|
||||
- name: host-sys
|
||||
hostPath:
|
||||
path: "/sys"
|
||||
|
|
|
@ -17,14 +17,27 @@ limitations under the License.
|
|||
package kernel
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/kubernetes-incubator/node-feature-discovery/source"
|
||||
)
|
||||
|
||||
// Default kconfig flags
|
||||
var defaultKconfigFlags = [...]string{
|
||||
"NO_HZ",
|
||||
"NO_HZ_IDLE",
|
||||
"NO_HZ_FULL",
|
||||
"PREEMPT",
|
||||
}
|
||||
|
||||
var logger = log.New(os.Stderr, "", log.LstdFlags)
|
||||
|
||||
// Implement FeatureSource interface
|
||||
type Source struct{}
|
||||
|
||||
|
@ -36,12 +49,26 @@ func (s Source) Discover() (source.Features, error) {
|
|||
// Read kernel version
|
||||
version, err := parseVersion()
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to get kernel version: %v", err)
|
||||
logger.Printf("ERROR: Failed to get kernel version: %s", err)
|
||||
} else {
|
||||
for key := range version {
|
||||
features["version."+key] = version[key]
|
||||
}
|
||||
}
|
||||
|
||||
// Read kconfig
|
||||
kconfig, err := parseKconfig()
|
||||
if err != nil {
|
||||
logger.Printf("ERROR: Failed to read kconfig: %s", err)
|
||||
}
|
||||
|
||||
// Check flags
|
||||
for _, flag := range defaultKconfigFlags {
|
||||
if _, ok := kconfig[flag]; ok {
|
||||
features["config."+flag] = true
|
||||
}
|
||||
}
|
||||
|
||||
return features, nil
|
||||
}
|
||||
|
||||
|
@ -70,3 +97,64 @@ func parseVersion() (map[string]string, error) {
|
|||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// Read gzipped kernel config
|
||||
func readKconfigGzip(filename string) ([]byte, error) {
|
||||
// Open file for reading
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Uncompress data
|
||||
r, err := gzip.NewReader(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
return ioutil.ReadAll(r)
|
||||
}
|
||||
|
||||
// Read kconfig into a map
|
||||
func parseKconfig() (map[string]bool, error) {
|
||||
kconfig := map[string]bool{}
|
||||
raw := []byte(nil)
|
||||
|
||||
// First, try to read from /proc as this is the most reliable source
|
||||
raw, err := readKconfigGzip("/proc/config.gz")
|
||||
if err != nil {
|
||||
logger.Printf("ERROR: Failed to read /proc/config.gz: %s", err)
|
||||
}
|
||||
|
||||
// Last, try to read from /boot/
|
||||
if raw == nil {
|
||||
// Get kernel version
|
||||
unameRaw, err := ioutil.ReadFile("/proc/sys/kernel/osrelease")
|
||||
uname := strings.TrimSpace(string(unameRaw))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Read kconfig
|
||||
raw, err = ioutil.ReadFile("/host-boot/config-" + uname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Regexp for matching kconfig flags
|
||||
re := regexp.MustCompile(`^CONFIG_(?P<flag>\w+)=(?P<value>.+)`)
|
||||
|
||||
// Process data, line-by-line
|
||||
lines := bytes.Split(raw, []byte("\n"))
|
||||
for _, line := range lines {
|
||||
if m := re.FindStringSubmatch(string(line)); m != nil {
|
||||
if m[2] == "y" || m[2] == "m" {
|
||||
kconfig[m[1]] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return kconfig, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue