Skip to content

Commit 9cd204c

Browse files
committed
Add swap support in nfd
1 parent e0b8a52 commit 9cd204c

File tree

9 files changed

+85
-0
lines changed

9 files changed

+85
-0
lines changed

deployment/components/common/worker-mounts.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
- name: host-boot
55
hostPath:
66
path: "/boot"
7+
- name: host-proc-swaps
8+
hostPath:
9+
path: "/proc/swaps"
710
- name: host-os-release
811
hostPath:
912
path: "/etc/os-release"
@@ -38,6 +41,9 @@
3841
- name: host-sys
3942
mountPath: "/host-sys"
4043
readOnly: true
44+
- name: host-proc-swaps
45+
mountPath: "/host-swaps"
46+
readOnly: true
4147
- name: host-usr-lib
4248
mountPath: "/host-usr/lib"
4349
readOnly: true

deployment/helm/node-feature-discovery/templates/worker.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ spec:
8787
- name: host-lib
8888
mountPath: "/host-lib"
8989
readOnly: true
90+
- name: host-proc-swaps
91+
W2AQ mountPath: "/host-proc/swaps"
92+
readOnly: true
9093
{{- if .Values.worker.mountUsrSrc }}
9194
- name: host-usr-src
9295
mountPath: "/host-usr/src"
@@ -122,6 +125,9 @@ spec:
122125
- name: host-lib
123126
hostPath:
124127
path: "/lib"
128+
- name: host-proc/swaps
129+
hostPath:
130+
path: "/proc/swaps"
125131
{{- if .Values.worker.mountUsrSrc }}
126132
- name: host-usr-src
127133
hostPath:

docs/usage/customization-guide.md

+2
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,8 @@ The following features are available for matching:
966966
| **`memory.numa`** | attribute | | | NUMA nodes |
967967
| | | **`is_numa`** | bool | `true` if NUMA architecture, `false` otherwise |
968968
| | | **`node_count`** | int | Number of NUMA nodes |
969+
| **`memory.swap`** | attribute | | | Swap enabled on node |
970+
| | | **`enabled`** | bool | `true` if swap partition detected, `false` otherwise |
969971
| **`network.device`** | instance | | | Physical (non-virtual) network interfaces present in the system |
970972
| | | **`name`** | string | Name of the network interface |
971973
| | | **`<sysfs-attribute>`** | string | Sysfs network interface attribute, available attributes: `operstate`, `speed`, `sriov_numvfs`, `sriov_totalvfs` |

docs/usage/features.md

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ configuration options for details.
177177
| **`memory-numa`** | true | Multiple memory nodes i.e. NUMA architecture detected |
178178
| **`memory-nv.present`** | true | NVDIMM device(s) are present |
179179
| **`memory-nv.dax`** | true | NVDIMM region(s) configured in DAX mode are present |
180+
| **`memory-swap.enabled`** | true | Swap is enabled on the node |
180181

181182
### Network
182183

pkg/utils/hostpath/hostpath.go

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ var (
3434
VarDir = HostDir(pathPrefix + "var")
3535
// LibDir is where the /lib directory of the system to be inspected is located
3636
LibDir = HostDir(pathPrefix + "lib")
37+
// ProcDir is where the /proc directory of the system to be inspected is located
38+
ProcDir = HostDir(pathPrefix + "proc")
3739
)
3840

3941
// HostDir is a helper for handling host system directories

source/memory/memory.go

+37
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ const NvFeature = "nv"
4040
// NumaFeature is the name of the feature set that holds all NUMA related features.
4141
const NumaFeature = "numa"
4242

43+
// SwapFeature is the name of the feature set that holds all Swap related features
44+
const SwapFeature = "swap"
45+
4346
// memorySource implements the FeatureSource and LabelSource interfaces.
4447
type memorySource struct {
4548
features *nfdv1alpha1.Features
@@ -68,6 +71,11 @@ func (s *memorySource) GetLabels() (source.FeatureLabels, error) {
6871
labels["numa"] = true
6972
}
7073

74+
// Swap
75+
if isSwap, ok := features.Attributes[SwapFeature].Elements["enabled"]; ok && isSwap == "true" {
76+
labels["swap"] = true
77+
}
78+
7179
// NVDIMM
7280
if len(features.Instances[NvFeature].Elements) > 0 {
7381
labels["nv.present"] = true
@@ -93,6 +101,13 @@ func (s *memorySource) Discover() error {
93101
s.features.Attributes[NumaFeature] = nfdv1alpha1.AttributeFeatureSet{Elements: numa}
94102
}
95103

104+
// Detect Swap
105+
if swap, err := detectSwap(); err != nil {
106+
klog.ErrorS(err, "failed to detect Swap nodes")
107+
} else {
108+
s.features.Attributes[SwapFeature] = nfdv1alpha1.AttributeFeatureSet{Elements: swap}
109+
}
110+
96111
// Detect NVDIMM
97112
if nv, err := detectNv(); err != nil {
98113
klog.ErrorS(err, "failed to detect nvdimm devices")
@@ -113,6 +128,20 @@ func (s *memorySource) GetFeatures() *nfdv1alpha1.Features {
113128
return s.features
114129
}
115130

131+
// detectSwap detects Swap node information
132+
func detectSwap() (map[string]string, error) {
133+
procBasePath := hostpath.ProcDir.Path("swaps")
134+
lines, err := getNumberOfLinesFromFile(procBasePath)
135+
if err != nil {
136+
return nil, fmt.Errorf("failed to read swaps file: %w", err)
137+
}
138+
// /proc/swaps has a header row
139+
// If there is more than a header then we assume we have swap.
140+
return map[string]string{
141+
"enabled": strconv.FormatBool(lines > 1),
142+
}, nil
143+
}
144+
116145
// detectNuma detects NUMA node information
117146
func detectNuma() (map[string]string, error) {
118147
sysfsBasePath := hostpath.SysfsDir.Path("bus/node/devices")
@@ -166,6 +195,14 @@ func readNdDeviceInfo(path string) nfdv1alpha1.InstanceFeature {
166195
return *nfdv1alpha1.NewInstanceFeature(attrs)
167196
}
168197

198+
func getNumberOfLinesFromFile(path string) (int, error) {
199+
data, err := os.ReadFile(path)
200+
if err != nil {
201+
return 0, err
202+
}
203+
return len(strings.Split(string(data), "\n")), nil
204+
}
205+
169206
func init() {
170207
source.Register(&src)
171208
}

source/memory/memory_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,33 @@ func TestMemorySource(t *testing.T) {
3131

3232
assert.Nil(t, err, err)
3333
assert.Empty(t, l)
34+
}
3435

36+
func TestGetNumberofLinesFromFile(t *testing.T) {
37+
type testCase struct {
38+
path string
39+
expectedLines int
40+
expectErr bool
41+
}
42+
tc := []testCase{
43+
{
44+
path: "testdata/swap",
45+
expectedLines: 2,
46+
},
47+
{
48+
path: "testdata/noswap",
49+
expectedLines: 1,
50+
},
51+
{
52+
path: "file_not_exist",
53+
expectErr: true,
54+
},
55+
}
56+
for _, tc := range tc {
57+
actual, err := getNumberOfLinesFromFile(tc.path)
58+
if tc.expectErr {
59+
assert.NotNil(t, err, "should get an error")
60+
}
61+
assert.Equal(t, tc.expectedLines, actual, "lines should match")
62+
}
3563
}

source/memory/testdata/noswap

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Filename Type Size Used Priority

source/memory/testdata/swap

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Filename Type Size Used Priority
2+
dummyfile partition 65555 0 -1

0 commit comments

Comments
 (0)