/* Copyright 2021 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 utils import ( "fmt" "os" "path/filepath" "testing" corev1 "k8s.io/api/core/v1" ) const ( HugepageSize2Mi = 2048 HugepageSize1Gi = 1048576 ) const testMeminfo = `Node 0 MemTotal: 32718644 kB Node 0 MemFree: 2915988 kB Node 0 MemUsed: 29802656 kB Node 0 Active: 19631832 kB Node 0 Inactive: 8089096 kB Node 0 Active(anon): 10104396 kB Node 0 Inactive(anon): 511432 kB Node 0 Active(file): 9527436 kB Node 0 Inactive(file): 7577664 kB Node 0 Unevictable: 637864 kB Node 0 Mlocked: 0 kB Node 0 Dirty: 1140 kB Node 0 Writeback: 0 kB Node 0 FilePages: 18206092 kB Node 0 Mapped: 2000244 kB Node 0 AnonPages: 10152780 kB Node 0 Shmem: 1249348 kB Node 0 KernelStack: 37440 kB Node 0 PageTables: 110460 kB Node 0 NFS_Unstable: 0 kB Node 0 Bounce: 0 kB Node 0 WritebackTmp: 0 kB Node 0 KReclaimable: 843624 kB Node 0 Slab: 1198060 kB Node 0 SReclaimable: 843624 kB Node 0 SUnreclaim: 354436 kB Node 0 AnonHugePages: 26624 kB Node 0 ShmemHugePages: 0 kB Node 0 ShmemPmdMapped: 0 kB Node 0 FileHugePages: 0 kB Node 0 FilePmdMapped: 0 kB Node 0 HugePages_Total: 0 Node 0 HugePages_Free: 0 Node 0 HugePages_Surp: 0` func TestGetMemoryResourceCounters(t *testing.T) { rootDir, err := os.MkdirTemp("", "fakehp") if err != nil { t.Errorf("failed to create temporary directory: %v", err) } defer os.RemoveAll(rootDir) // clean up sysBusNodeBasepath = rootDir // set mock hugepages if err := makeHugepagesTree(rootDir, 2); err != nil { t.Errorf("failed to setup the fake tree on %q: %v", rootDir, err) } if err := setHPCount(rootDir, 0, HugepageSize2Mi, 6); err != nil { t.Errorf("failed to setup hugepages on node %d the fake tree on %q: %v", 0, rootDir, err) } if err := setHPCount(rootDir, 1, HugepageSize2Mi, 8); err != nil { t.Errorf("failed to setup hugepages on node %d the fake tree on %q: %v", 0, rootDir, err) } // set mock memory if err := makeMemoryTree(rootDir, 2); err != nil { t.Errorf("failed to setup the fake tree on %q: %v", rootDir, err) } memoryCounters, err := GetNumaMemoryResources() if err != nil { t.Errorf("unexpected error: %v", err) } if memoryCounters[0]["hugepages-2Mi"] != 12582912 { t.Errorf("found unexpected amount of 2Mi hugepages under the NUMA node 0: %d", memoryCounters[0]["hugepages-2Mi"]) } if memoryCounters[1]["hugepages-2Mi"] != 16777216 { t.Errorf("found unexpected amount of 2Mi hugepages under the NUMA node 1: %d", memoryCounters[1]["hugepages-2Mi"]) } if memoryCounters[0]["hugepages-1Gi"] != 0 { t.Errorf("found unexpected 1Gi hugepages for node 0: %v", memoryCounters[0]["hugepages-1Gi"]) } if memoryCounters[1]["hugepages-1Gi"] != 0 { t.Errorf("found unexpected 1Gi hugepages for node 1: %v", memoryCounters[0]["hugepages-1Gi"]) } if memoryCounters[0]["memory"] != 32718644*1024 { t.Errorf("found unexpected amount of memory under the NUMA node 0: %d", memoryCounters[0][corev1.ResourceMemory]) } if memoryCounters[1]["memory"] != 32718644*1024 { t.Errorf("found unexpected amount of memory under the NUMA node 1: %d", memoryCounters[0][corev1.ResourceMemory]) } } func makeMemoryTree(root string, numNodes int) error { for idx := 0; idx < numNodes; idx++ { path := filepath.Join( root, fmt.Sprintf("node%d", idx), ) if err := os.MkdirAll(path, 0755); err != nil { return err } meminfoFile := filepath.Join(path, "meminfo") if err := os.WriteFile(meminfoFile, []byte(testMeminfo), 0644); err != nil { return err } } return nil } func makeHugepagesTree(root string, numNodes int) error { for idx := 0; idx < numNodes; idx++ { for _, size := range []int{HugepageSize2Mi, HugepageSize1Gi} { path := filepath.Join( root, fmt.Sprintf("node%d", idx), "hugepages", fmt.Sprintf("hugepages-%dkB", size), ) if err := os.MkdirAll(path, 0755); err != nil { return err } if err := setHPCount(root, idx, size, 0); err != nil { return err } } } return nil } func setHPCount(root string, nodeID, pageSize, numPages int) error { path := filepath.Join( root, fmt.Sprintf("node%d", nodeID), "hugepages", fmt.Sprintf("hugepages-%dkB", pageSize), "nr_hugepages", ) return os.WriteFile(path, []byte(fmt.Sprintf("%d", numPages)), 0644) }