Skip to content

Commit

Permalink
Add swap support in nfd
Browse files Browse the repository at this point in the history
  • Loading branch information
kannon92 committed Feb 18, 2024
1 parent e0b8a52 commit 9cd204c
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 0 deletions.
6 changes: 6 additions & 0 deletions deployment/components/common/worker-mounts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
- name: host-boot
hostPath:
path: "/boot"
- name: host-proc-swaps
hostPath:
path: "/proc/swaps"
- name: host-os-release
hostPath:
path: "/etc/os-release"
Expand Down Expand Up @@ -38,6 +41,9 @@
- name: host-sys
mountPath: "/host-sys"
readOnly: true
- name: host-proc-swaps
mountPath: "/host-swaps"
readOnly: true
- name: host-usr-lib
mountPath: "/host-usr/lib"
readOnly: true
Expand Down
6 changes: 6 additions & 0 deletions deployment/helm/node-feature-discovery/templates/worker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ spec:
- name: host-lib
mountPath: "/host-lib"
readOnly: true
- name: host-proc-swaps
W2AQ mountPath: "/host-proc/swaps"
readOnly: true
{{- if .Values.worker.mountUsrSrc }}
- name: host-usr-src
mountPath: "/host-usr/src"
Expand Down Expand Up @@ -122,6 +125,9 @@ spec:
- name: host-lib
hostPath:
path: "/lib"
- name: host-proc/swaps
hostPath:
path: "/proc/swaps"
{{- if .Values.worker.mountUsrSrc }}
- name: host-usr-src
hostPath:
Expand Down
2 changes: 2 additions & 0 deletions docs/usage/customization-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,8 @@ The following features are available for matching:
| **`memory.numa`** | attribute | | | NUMA nodes |
| | | **`is_numa`** | bool | `true` if NUMA architecture, `false` otherwise |
| | | **`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 |
| | | **`name`** | string | Name of the network interface |
| | | **`<sysfs-attribute>`** | string | Sysfs network interface attribute, available attributes: `operstate`, `speed`, `sriov_numvfs`, `sriov_totalvfs` |
Expand Down
1 change: 1 addition & 0 deletions docs/usage/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ configuration options for details.
| **`memory-numa`** | true | Multiple memory nodes i.e. NUMA architecture detected |
| **`memory-nv.present`** | true | NVDIMM device(s) 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

Expand Down
2 changes: 2 additions & 0 deletions pkg/utils/hostpath/hostpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ var (
VarDir = HostDir(pathPrefix + "var")
// LibDir is where the /lib directory of the system to be inspected is located
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
Expand Down
37 changes: 37 additions & 0 deletions source/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ const NvFeature = "nv"
// NumaFeature is the name of the feature set that holds all NUMA related features.
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.
type memorySource struct {
features *nfdv1alpha1.Features
Expand Down Expand Up @@ -68,6 +71,11 @@ func (s *memorySource) GetLabels() (source.FeatureLabels, error) {
labels["numa"] = true
}

// Swap
if isSwap, ok := features.Attributes[SwapFeature].Elements["enabled"]; ok && isSwap == "true" {
labels["swap"] = true
}

// NVDIMM
if len(features.Instances[NvFeature].Elements) > 0 {
labels["nv.present"] = true
Expand All @@ -93,6 +101,13 @@ func (s *memorySource) Discover() error {
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
if nv, err := detectNv(); err != nil {
klog.ErrorS(err, "failed to detect nvdimm devices")
Expand All @@ -113,6 +128,20 @@ func (s *memorySource) GetFeatures() *nfdv1alpha1.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
func detectNuma() (map[string]string, error) {
sysfsBasePath := hostpath.SysfsDir.Path("bus/node/devices")
Expand Down Expand Up @@ -166,6 +195,14 @@ func readNdDeviceInfo(path string) nfdv1alpha1.InstanceFeature {
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() {
source.Register(&src)
}
28 changes: 28 additions & 0 deletions source/memory/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,33 @@ func TestMemorySource(t *testing.T) {

assert.Nil(t, err, err)
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 change: 1 addition & 0 deletions source/memory/testdata/noswap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Filename Type Size Used Priority
2 changes: 2 additions & 0 deletions source/memory/testdata/swap
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Filename Type Size Used Priority
dummyfile partition 65555 0 -1

0 comments on commit 9cd204c

Please sign in to comment.