mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-16 21:38:23 +00:00
Merge pull request #1585 from kannon92/add-swap-support
add swap support in nfd
This commit is contained in:
commit
797fada92e
9 changed files with 86 additions and 1 deletions
|
@ -4,6 +4,9 @@
|
||||||
- name: host-boot
|
- name: host-boot
|
||||||
hostPath:
|
hostPath:
|
||||||
path: "/boot"
|
path: "/boot"
|
||||||
|
- name: host-proc-swaps
|
||||||
|
hostPath:
|
||||||
|
path: "/proc/swaps"
|
||||||
- name: host-os-release
|
- name: host-os-release
|
||||||
hostPath:
|
hostPath:
|
||||||
path: "/etc/os-release"
|
path: "/etc/os-release"
|
||||||
|
@ -38,6 +41,9 @@
|
||||||
- name: host-sys
|
- name: host-sys
|
||||||
mountPath: "/host-sys"
|
mountPath: "/host-sys"
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
- name: host-proc-swaps
|
||||||
|
mountPath: "/host-proc/swaps"
|
||||||
|
readOnly: true
|
||||||
- name: host-usr-lib
|
- name: host-usr-lib
|
||||||
mountPath: "/host-usr/lib"
|
mountPath: "/host-usr/lib"
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
|
|
@ -93,6 +93,9 @@ spec:
|
||||||
- name: host-lib
|
- name: host-lib
|
||||||
mountPath: "/host-lib"
|
mountPath: "/host-lib"
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
- name: host-proc-swaps
|
||||||
|
mountPath: "/host-proc/swaps"
|
||||||
|
readOnly: true
|
||||||
{{- if .Values.worker.mountUsrSrc }}
|
{{- if .Values.worker.mountUsrSrc }}
|
||||||
- name: host-usr-src
|
- name: host-usr-src
|
||||||
mountPath: "/host-usr/src"
|
mountPath: "/host-usr/src"
|
||||||
|
@ -128,6 +131,9 @@ spec:
|
||||||
- name: host-lib
|
- name: host-lib
|
||||||
hostPath:
|
hostPath:
|
||||||
path: "/lib"
|
path: "/lib"
|
||||||
|
- name: host-proc/swaps
|
||||||
|
hostPath:
|
||||||
|
path: "/proc/swaps"
|
||||||
{{- if .Values.worker.mountUsrSrc }}
|
{{- if .Values.worker.mountUsrSrc }}
|
||||||
- name: host-usr-src
|
- name: host-usr-src
|
||||||
hostPath:
|
hostPath:
|
||||||
|
|
|
@ -966,6 +966,8 @@ The following features are available for matching:
|
||||||
| **`memory.numa`** | attribute | | | NUMA nodes |
|
| **`memory.numa`** | attribute | | | NUMA nodes |
|
||||||
| | | **`is_numa`** | bool | `true` if NUMA architecture, `false` otherwise |
|
| | | **`is_numa`** | bool | `true` if NUMA architecture, `false` otherwise |
|
||||||
| | | **`node_count`** | int | Number of NUMA nodes |
|
| | | **`node_count`** | int | Number of NUMA nodes |
|
||||||
|
| **`memory.swap`** | attribute | | | Swap enabled on node |
|
||||||
|
| | | **`enabled`** | bool | `true` if swap partition detected, `false` otherwise |
|
||||||
| **`network.device`** | instance | | | Physical (non-virtual) network interfaces present in the system |
|
| **`network.device`** | instance | | | Physical (non-virtual) network interfaces present in the system |
|
||||||
| | | **`name`** | string | Name of the network interface |
|
| | | **`name`** | string | Name of the network interface |
|
||||||
| | | **`<sysfs-attribute>`** | string | Sysfs network interface attribute, available attributes: `operstate`, `speed`, `sriov_numvfs`, `sriov_totalvfs` |
|
| | | **`<sysfs-attribute>`** | string | Sysfs network interface attribute, available attributes: `operstate`, `speed`, `sriov_numvfs`, `sriov_totalvfs` |
|
||||||
|
|
|
@ -177,6 +177,7 @@ configuration options for details.
|
||||||
| **`memory-numa`** | true | Multiple memory nodes i.e. NUMA architecture detected |
|
| **`memory-numa`** | true | Multiple memory nodes i.e. NUMA architecture detected |
|
||||||
| **`memory-nv.present`** | true | NVDIMM device(s) are present |
|
| **`memory-nv.present`** | true | NVDIMM device(s) are present |
|
||||||
| **`memory-nv.dax`** | true | NVDIMM region(s) configured in DAX mode are present |
|
| **`memory-nv.dax`** | true | NVDIMM region(s) configured in DAX mode are present |
|
||||||
|
| **`memory-swap.enabled`** | true | Swap is enabled on the node |
|
||||||
|
|
||||||
### Network
|
### Network
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ var (
|
||||||
VarDir = HostDir(pathPrefix + "var")
|
VarDir = HostDir(pathPrefix + "var")
|
||||||
// LibDir is where the /lib directory of the system to be inspected is located
|
// LibDir is where the /lib directory of the system to be inspected is located
|
||||||
LibDir = HostDir(pathPrefix + "lib")
|
LibDir = HostDir(pathPrefix + "lib")
|
||||||
|
// ProcDir is where the /proc directory of the system to be inspected is located
|
||||||
|
ProcDir = HostDir(pathPrefix + "proc")
|
||||||
)
|
)
|
||||||
|
|
||||||
// HostDir is a helper for handling host system directories
|
// HostDir is a helper for handling host system directories
|
||||||
|
|
|
@ -40,6 +40,9 @@ const NvFeature = "nv"
|
||||||
// NumaFeature is the name of the feature set that holds all NUMA related features.
|
// NumaFeature is the name of the feature set that holds all NUMA related features.
|
||||||
const NumaFeature = "numa"
|
const NumaFeature = "numa"
|
||||||
|
|
||||||
|
// SwapFeature is the name of the feature set that holds all Swap related features
|
||||||
|
const SwapFeature = "swap"
|
||||||
|
|
||||||
// memorySource implements the FeatureSource and LabelSource interfaces.
|
// memorySource implements the FeatureSource and LabelSource interfaces.
|
||||||
type memorySource struct {
|
type memorySource struct {
|
||||||
features *nfdv1alpha1.Features
|
features *nfdv1alpha1.Features
|
||||||
|
@ -68,6 +71,11 @@ func (s *memorySource) GetLabels() (source.FeatureLabels, error) {
|
||||||
labels["numa"] = true
|
labels["numa"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Swap
|
||||||
|
if isSwap, ok := features.Attributes[SwapFeature].Elements["enabled"]; ok && isSwap == "true" {
|
||||||
|
labels["swap"] = true
|
||||||
|
}
|
||||||
|
|
||||||
// NVDIMM
|
// NVDIMM
|
||||||
if len(features.Instances[NvFeature].Elements) > 0 {
|
if len(features.Instances[NvFeature].Elements) > 0 {
|
||||||
labels["nv.present"] = true
|
labels["nv.present"] = true
|
||||||
|
@ -93,6 +101,13 @@ func (s *memorySource) Discover() error {
|
||||||
s.features.Attributes[NumaFeature] = nfdv1alpha1.AttributeFeatureSet{Elements: numa}
|
s.features.Attributes[NumaFeature] = nfdv1alpha1.AttributeFeatureSet{Elements: numa}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect Swap
|
||||||
|
if swap, err := detectSwap(); err != nil {
|
||||||
|
klog.ErrorS(err, "failed to detect Swap nodes")
|
||||||
|
} else {
|
||||||
|
s.features.Attributes[SwapFeature] = nfdv1alpha1.AttributeFeatureSet{Elements: swap}
|
||||||
|
}
|
||||||
|
|
||||||
// Detect NVDIMM
|
// Detect NVDIMM
|
||||||
if nv, err := detectNv(); err != nil {
|
if nv, err := detectNv(); err != nil {
|
||||||
klog.ErrorS(err, "failed to detect nvdimm devices")
|
klog.ErrorS(err, "failed to detect nvdimm devices")
|
||||||
|
@ -113,6 +128,20 @@ func (s *memorySource) GetFeatures() *nfdv1alpha1.Features {
|
||||||
return s.features
|
return s.features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// detectSwap detects Swap node information
|
||||||
|
func detectSwap() (map[string]string, error) {
|
||||||
|
procBasePath := hostpath.ProcDir.Path("swaps")
|
||||||
|
lines, err := getNumberOfLinesFromFile(procBasePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read swaps file: %w", err)
|
||||||
|
}
|
||||||
|
// /proc/swaps has a header row
|
||||||
|
// If there is more than a header then we assume we have swap.
|
||||||
|
return map[string]string{
|
||||||
|
"enabled": strconv.FormatBool(lines > 1),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// detectNuma detects NUMA node information
|
// detectNuma detects NUMA node information
|
||||||
func detectNuma() (map[string]string, error) {
|
func detectNuma() (map[string]string, error) {
|
||||||
sysfsBasePath := hostpath.SysfsDir.Path("bus/node/devices")
|
sysfsBasePath := hostpath.SysfsDir.Path("bus/node/devices")
|
||||||
|
@ -166,6 +195,14 @@ func readNdDeviceInfo(path string) nfdv1alpha1.InstanceFeature {
|
||||||
return *nfdv1alpha1.NewInstanceFeature(attrs)
|
return *nfdv1alpha1.NewInstanceFeature(attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNumberOfLinesFromFile(path string) (int, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(strings.Split(string(data), "\n")), nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
source.Register(&src)
|
source.Register(&src)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,5 +31,33 @@ func TestMemorySource(t *testing.T) {
|
||||||
|
|
||||||
assert.Nil(t, err, err)
|
assert.Nil(t, err, err)
|
||||||
assert.Empty(t, l)
|
assert.Empty(t, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNumberofLinesFromFile(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
path string
|
||||||
|
expectedLines int
|
||||||
|
expectErr bool
|
||||||
|
}
|
||||||
|
tc := []testCase{
|
||||||
|
{
|
||||||
|
path: "testdata/swap",
|
||||||
|
expectedLines: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "testdata/noswap",
|
||||||
|
expectedLines: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "file_not_exist",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range tc {
|
||||||
|
actual, err := getNumberOfLinesFromFile(tc.path)
|
||||||
|
if tc.expectErr {
|
||||||
|
assert.NotNil(t, err, "should get an error")
|
||||||
|
}
|
||||||
|
assert.Equal(t, tc.expectedLines, actual, "lines should match")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1
source/memory/testdata/noswap
vendored
Normal file
1
source/memory/testdata/noswap
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Filename Type Size Used Priority
|
2
source/memory/testdata/swap
vendored
Normal file
2
source/memory/testdata/swap
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Filename Type Size Used Priority
|
||||||
|
dummyfile partition 65555 0 -1
|
Loading…
Add table
Reference in a new issue