From 2732046278ea07196e043c9a85b8226490382c39 Mon Sep 17 00:00:00 2001 From: "Niranjan M.R" Date: Sat, 18 Jul 2026 16:25:11 +0530 Subject: [PATCH 1/4] E2E: ovs: Use systemctl reboot instead of modifying profile Earlier we used to modify performance profile to trigger reboot i.e change the topology manager to best-effort. This is problem when ran on ARM where changing topology manager to best-effort or any other value other than none causes ARM worker node to get stuck So instead we now use systemctl reboot to reboot the node Signed-off-by: Niranjan M.R --- .../7_performance_kubelet_node/cgroups.go | 63 +++---------------- 1 file changed, 10 insertions(+), 53 deletions(-) diff --git a/test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go b/test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go index 029acc1ce..b1131d156 100644 --- a/test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go +++ b/test/e2e/performanceprofile/functests/7_performance_kubelet_node/cgroups.go @@ -3,7 +3,6 @@ package __performance_kubelet_node_test import ( "bytes" "context" - "encoding/json" "fmt" "path/filepath" "strconv" @@ -33,9 +32,7 @@ import ( testlog "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/log" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/nodes" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/pods" - "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/poolname" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/profiles" - "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/profilesupdate" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/systemd" ) @@ -58,8 +55,7 @@ var _ = Describe("[performance] Cgroups and affinity", Ordered, Label(string(lab isolatedCPUSet cpuset.CPUSet workerRTNode *corev1.Node workerRTNodes []corev1.Node - profile, initialProfile *performancev2.PerformanceProfile - poolName string + profile *performancev2.PerformanceProfile ovsSliceCgroup string ctx context.Context = context.Background() ovsSystemdServices []string @@ -89,8 +85,6 @@ var _ = Describe("[performance] Cgroups and affinity", Ordered, Label(string(lab profile, err = profiles.GetByNodeLabels(testutils.NodeSelectorLabels) Expect(err).ToNot(HaveOccurred()) - poolName = poolname.GetByProfile(ctx, profile) - isCgroupV2, err = cgroup.IsVersion2(ctx, testclient.DataPlaneClient) Expect(err).ToNot(HaveOccurred()) @@ -160,56 +154,19 @@ var _ = Describe("[performance] Cgroups and affinity", Ordered, Label(string(lab }) - Context("[Performance Profile Modified]", Label(string(label.Tier1)), func() { - BeforeEach(func() { - initialProfile = profile.DeepCopy() - }) + Context("[Node Reboot]", Label(string(label.Tier1)), func() { It("[test_id:64099] Activation file doesn't get deleted", func() { - policy := "best-effort" - // Need to make some changes to pp , causing system reboot - // and check if activation files is modified or deleted - profile, err := profiles.GetByNodeLabels(testutils.NodeSelectorLabels) - Expect(err).ToNot(HaveOccurred(), "Unable to fetch latest performance profile") - currentPolicy := profile.Spec.NUMA.TopologyPolicy - if *currentPolicy == "best-effort" { - policy = "restricted" - } - profile.Spec.NUMA = &performancev2.NUMA{ - TopologyPolicy: &policy, - } - By("Updating the performance profile") - profiles.UpdateWithRetry(profile) - - By(fmt.Sprintf("Applying changes in performance profile and waiting until %s will start updating", poolName)) - profilesupdate.WaitForTuningUpdating(ctx, profile) - - By(fmt.Sprintf("Waiting when %s finishes updates", poolName)) - profilesupdate.WaitForTuningUpdated(ctx, profile) + By(fmt.Sprintf("Rebooting the worker node %q", workerRTNode.Name)) + _, _ = nodes.ExecCommand(ctx, workerRTNode, []string{"sh", "-c", "chroot /rootfs systemctl reboot"}) + nodes.WaitForNotReadyOrFail("Reboot", workerRTNode.Name, 10*time.Minute, 30*time.Second) + nodes.WaitForReadyOrFail("Reboot", workerRTNode.Name, 10*time.Minute, 30*time.Second) By("Checking Activation file") cmd := []string{"ls", activation_file} - for _, node := range workerRTNodes { - output, err := nodes.ExecCommand(context.TODO(), &node, cmd) - Expect(err).ToNot(HaveOccurred(), "file %s doesn't exist ", activation_file) - out := testutils.ToString(output) - Expect(out).To(Equal(activation_file)) - } - }) - AfterEach(func() { - By("Reverting the Profile") - profile, err := profiles.GetByNodeLabels(testutils.NodeSelectorLabels) - Expect(err).ToNot(HaveOccurred()) - currentSpec, _ := json.Marshal(profile.Spec) - spec, _ := json.Marshal(initialProfile.Spec) - if !bytes.Equal(currentSpec, spec) { - profiles.UpdateWithRetry(initialProfile) - - By(fmt.Sprintf("Applying changes in performance profile and waiting until %s will start updating", poolName)) - profilesupdate.WaitForTuningUpdating(ctx, profile) - - By(fmt.Sprintf("Waiting when %s finishes updates", poolName)) - profilesupdate.WaitForTuningUpdated(ctx, profile) - } + output, err := nodes.ExecCommand(context.TODO(), workerRTNode, cmd) + Expect(err).ToNot(HaveOccurred(), "file %s doesn't exist", activation_file) + out := testutils.ToString(output) + Expect(out).To(Equal(activation_file)) }) }) }) From 52e9b1b003ba3b350b91e3f19619883ac20ae034 Mon Sep 17 00:00:00 2001 From: "Niranjan M.R" Date: Sat, 18 Jul 2026 16:27:35 +0530 Subject: [PATCH 2/4] E2E: annotations. modify existing tests to preserve existing annotations Earlier when kubelet experimental annotions e2e tests ran , it used to overwrite any existing annotations. When running on clusters deployed using ztp, the existing annotations need to be honoured. Modify the existing tests to honor the existing annotations. Also skip the tests if architecture is ARM where the annotations set kublet topology manager to any value other than none Signed-off-by: Niranjan M.R --- .../7_performance_kubelet_node/kubelet.go | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go b/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go index 6f37f2724..6775bbfdf 100644 --- a/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go +++ b/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go @@ -2,7 +2,6 @@ package __performance_kubelet_node_test import ( "context" - "encoding/json" "fmt" "strconv" "strings" @@ -24,6 +23,7 @@ import ( testutils "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils" testclient "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/client" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/hypershift" + "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/infrastructure" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/label" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/nodes" "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/poolname" @@ -58,6 +58,11 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord }) Context("Additional kubelet arguments", Label(string(label.Tier2)), func() { + BeforeEach(func() { + var err error + profile, err = profiles.GetByNodeLabels(testutils.NodeSelectorLabels) + Expect(err).ToNot(HaveOccurred()) + }) It("[test_id:45488]Test performance profile annotation for changing multiple kubelet settings", func() { sysctls := "{\"allowedUnsafeSysctls\":[\"net.core.somaxconn\",\"kernel.msg*\"],\"systemReserved\":{\"memory\":\"300Mi\"},\"kubeReserved\":{\"memory\":\"768Mi\"},\"imageMinimumGCAge\":\"3m\"}" profile.Annotations = updateKubeletConfigOverrideAnnotations(profile.Annotations, sysctls) @@ -164,6 +169,15 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord } }) It("[test_id:45495] Test setting PAO managed parameters", func() { + cnfNodes, err := nodes.GetByLabels(testutils.NodeSelectorLabels) + Expect(err).ToNot(HaveOccurred()) + Expect(len(cnfNodes)).To(BeNumerically(">", 0), "expected at least one node to match the selector") + isArm, err := infrastructure.IsARM(ctx, &cnfNodes[0]) + Expect(err).ToNot(HaveOccurred()) + if isArm { + Skip("Changing topologyManagerPolicy is not supported on ARM architecture") + } + var paoParameters string if *profile.Spec.NUMA.TopologyPolicy == "single-numa-node" { paoParameters = "{\"topologyManagerPolicy\":\"restricted\"}" @@ -216,10 +230,8 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord By("Reverting the Profile") profile, err := profiles.GetByNodeLabels(testutils.NodeSelectorLabels) Expect(err).ToNot(HaveOccurred()) - currentSpec, _ := json.Marshal(profile.Spec) - spec, _ := json.Marshal(initialProfile.Spec) // revert only if the profile changes. - if !equality.Semantic.DeepEqual(currentSpec, spec) { + if !equality.Semantic.DeepEqual(profile.Spec, initialProfile.Spec) || !equality.Semantic.DeepEqual(profile.Annotations, initialProfile.Annotations) { profiles.UpdateWithRetry(initialProfile) By(fmt.Sprintf("Applying changes in performance profile and waiting until %s will start updating", poolName)) From 1b1d8d0dd20eaa3acbe76684fd6e8c645677486a Mon Sep 17 00:00:00 2001 From: "Niranjan M.R" Date: Sat, 18 Jul 2026 16:30:33 +0530 Subject: [PATCH 3/4] E2E: mustgather: Fetch performance profile instead of hardcoding Instead of using hardcoded performance profile name, fetch the performance profile name Signed-off-by: Niranjan M.R --- .../functests/6_mustgather_testing/mustgather.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/e2e/performanceprofile/functests/6_mustgather_testing/mustgather.go b/test/e2e/performanceprofile/functests/6_mustgather_testing/mustgather.go index 706b6bf7d..80a6aa644 100644 --- a/test/e2e/performanceprofile/functests/6_mustgather_testing/mustgather.go +++ b/test/e2e/performanceprofile/functests/6_mustgather_testing/mustgather.go @@ -10,6 +10,7 @@ import ( "strings" machineconfigv1 "github.com/openshift/api/machineconfiguration/v1" + "github.com/openshift/cluster-node-tuning-operator/pkg/performanceprofile/controller/performanceprofile/components" testutils "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils" testclient "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/client" hypershiftutils "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/hypershift" @@ -61,16 +62,18 @@ var _ = Describe("[rfe_id: 50649] Performance Addon Operator Must Gather", Label if profile == nil { Skip("No Performance Profile found") } - //replace peformance.yaml for profile.Name when data is generated in the node + profileName := profile.Name + kubeletConfigName := components.GetComponentName(profileName, components.ComponentNamePrefix) + tunedName := components.GetComponentName(profileName, components.ProfileNamePerformance) ClusterSpecificFiles := []string{ - "cluster-scoped-resources/performance.openshift.io/performanceprofiles/performance.yaml", - "cluster-scoped-resources/machineconfiguration.openshift.io/kubeletconfigs/performance-performance.yaml", - "namespaces/openshift-cluster-node-tuning-operator/tuned.openshift.io/tuneds/openshift-node-performance-performance.yaml", + fmt.Sprintf("cluster-scoped-resources/performance.openshift.io/performanceprofiles/%s.yaml", profileName), + fmt.Sprintf("cluster-scoped-resources/machineconfiguration.openshift.io/kubeletconfigs/%s.yaml", kubeletConfigName), + fmt.Sprintf("namespaces/openshift-cluster-node-tuning-operator/tuned.openshift.io/tuneds/%s.yaml", tunedName), } // On a hypershift env, the tuned file name has an indentifier in the end if hypershiftutils.IsHypershiftCluster() { ClusterSpecificFiles = []string{ - "namespaces/openshift-cluster-node-tuning-operator/tuned.openshift.io/tuneds/openshift-node-performance-performance-*.yaml", + fmt.Sprintf("namespaces/openshift-cluster-node-tuning-operator/tuned.openshift.io/tuneds/%s-*.yaml", tunedName), } } By(fmt.Sprintf("Checking Folder: %q\n", mgContentFolder)) From b51cfaa515d23d1829defc4a1a317344ada526e8 Mon Sep 17 00:00:00 2001 From: "Niranjan M.R" Date: Thu, 23 Jul 2026 11:29:30 +0530 Subject: [PATCH 4/4] E2E: kubelet Experimental Annotation fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test 45488 — Multiple kubelet settings 1. Removed broken ps -ef | grep kubelet block — systemReserved is in the drop-in config (/etc/openshift/kubelet.conf.d/20-auto-sizing.conf), not in kubelet CLI flags or kubelet.conf 2. Added check via drop-in config file — reads 20-auto-sizing.conf from the node and verifies it contains 300Mi Test 45493 — Should not override PAO values 3. Changed annotation values to differ from PAO defaults — was setting cpuManagerPolicy: "static" and cpuManagerReconcilePeriod: "5s" (same as what PAO sets, proving nothing). Now sets "none" and "10s", and verifies PAO overrides them back to "static" and 5s Test 45490 — Memory reservation changes 4. Re-fetch nodes after tuning update — workerRTNodes was populated in CustomBeforeAll with stale node.Status values. Now re-fetches nodes so Capacity and Allocatable reflect the updated reservations 5. Account for hugepages in allocatable calculation — pre-allocated hugepages are subtracted from allocatable memory by the kubelet but included in node capacity. Added loop to sum hugepages from node.Status.Capacity and subtract from calculated allocatable Test 45489 — Verify settings are reverted 6. Use WaitForTuningUpdated instead of WaitForTuningUpdating — the revert may not trigger an MCP update when the only annotation difference is a PAO-overridden value (e.g., topologyManagerPolicy set via annotation is always overridden by the profile spec, so removing it produces the same rendered KubeletConfig). WaitForTuningUpdated checks Updated=True which passes immediately if no MCP rollout was needed, or waits for completion if one was triggered. Applied same fix in AfterAll. 7. Replaced systemReserved check — same as 45488: removed ps -ef approach, added drop-in config file check verifying 300Mi is no longer present 8. Fixed nil vs empty slice assertion — changed Equal(nil) to BeEmpty() for AllowedUnsafeSysctls, since after reverting it's an empty slice ([]string{}), not nil 9. Replaced context.TODO() with ctx — all ExecCommand, GetKubeletConfig, and ControlPlaneClient.Get calls now use the existing ctx (context.Background()) variable for consistent context usage 10. Added non-emptiness checks for node slices — workerRTNodes and updatedNodes are now validated after MatchingOptionalSelector to prevent out-of-bounds panics 11. Use workerRTNodes for ARM check — replaced separate cnfNodes lookup with workerRTNodes[0] to ensure the ARM check targets the same filtered node set used by the tests AI Attribution: AIA Human-AI blend, Content edits Signed-off-by: Niranjan M.R --- .../7_performance_kubelet_node/kubelet.go | 88 ++++++++++++------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go b/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go index 6775bbfdf..3999f00d6 100644 --- a/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go +++ b/test/e2e/performanceprofile/functests/7_performance_kubelet_node/kubelet.go @@ -41,14 +41,13 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord ) testutils.CustomBeforeAll(func() { - // TODO: The code here is broken as it masks workerRTNodes defined above - // and the value of workerRTNodes is never used. Keep the linter happy for now - // and remove the ineffectual assignment of workerRTNodes, err = nodes.MatchingOptionalSelector(workerRTNodes) below. - workerRTNodes, err := nodes.GetByLabels(testutils.NodeSelectorLabels) + var err error + workerRTNodes, err = nodes.GetByLabels(testutils.NodeSelectorLabels) Expect(err).ToNot(HaveOccurred()) - _, err = nodes.MatchingOptionalSelector(workerRTNodes) + workerRTNodes, err = nodes.MatchingOptionalSelector(workerRTNodes) Expect(err).ToNot(HaveOccurred()) + Expect(workerRTNodes).ToNot(BeEmpty(), "no RT worker nodes found") profile, err = profiles.GetByNodeLabels(testutils.NodeSelectorLabels) Expect(err).ToNot(HaveOccurred()) @@ -63,6 +62,7 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord profile, err = profiles.GetByNodeLabels(testutils.NodeSelectorLabels) Expect(err).ToNot(HaveOccurred()) }) + It("[test_id:45488]Test performance profile annotation for changing multiple kubelet settings", func() { sysctls := "{\"allowedUnsafeSysctls\":[\"net.core.somaxconn\",\"kernel.msg*\"],\"systemReserved\":{\"memory\":\"300Mi\"},\"kubeReserved\":{\"memory\":\"768Mi\"},\"imageMinimumGCAge\":\"3m\"}" profile.Annotations = updateKubeletConfigOverrideAnnotations(profile.Annotations, sysctls) @@ -77,24 +77,25 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord profilesupdate.WaitForTuningUpdated(ctx, profile) for _, node := range workerRTNodes { - kubeletConfig, err := nodes.GetKubeletConfig(context.TODO(), &node) + kubeletConfig, err := nodes.GetKubeletConfig(ctx, &node) Expect(err).ToNot(HaveOccurred()) sysctlsValue := kubeletConfig.AllowedUnsafeSysctls Expect(sysctlsValue).Should(ContainElements("net.core.somaxconn", "kernel.msg*")) Expect(kubeletConfig.KubeReserved["memory"]).To(Equal("768Mi")) - Expect(kubeletConfig.ImageMinimumGCAge.Seconds()).To(Equal(180)) + Expect(kubeletConfig.ImageMinimumGCAge.Seconds()).To(BeNumerically("==", 180)) } - kubeletArguments := []string{"/bin/bash", "-c", "ps -ef | grep kubelet | grep config"} + + autoSizingCmd := []string{"cat", "/rootfs/etc/openshift/kubelet.conf.d/20-auto-sizing.conf"} for _, node := range workerRTNodes { - out, err := nodes.ExecCommand(context.TODO(), &node, kubeletArguments) + out, err := nodes.ExecCommand(ctx, &node, autoSizingCmd) Expect(err).ToNot(HaveOccurred()) stdout := testutils.ToString(out) - Expect(strings.Contains(stdout, "300Mi")).To(BeTrue()) + Expect(stdout).To(ContainSubstring("300Mi")) } }) Context("When setting cpu manager related parameters", func() { It("[test_id:45493]Should not override performance-addon-operator values", func() { - paoValues := "{\"cpuManagerPolicy\":\"static\",\"cpuManagerReconcilePeriod\":\"5s\"}" + paoValues := "{\"cpuManagerPolicy\":\"none\",\"cpuManagerReconcilePeriod\":\"10s\"}" profile.Annotations = updateKubeletConfigOverrideAnnotations(profile.Annotations, paoValues) By("updating Performance profile") @@ -107,10 +108,10 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord profilesupdate.WaitForTuningUpdated(ctx, profile) for _, node := range workerRTNodes { - kubeletConfig, err := nodes.GetKubeletConfig(context.TODO(), &node) + kubeletConfig, err := nodes.GetKubeletConfig(ctx, &node) Expect(err).ToNot(HaveOccurred()) Expect(kubeletConfig.CPUManagerPolicy).Should(Equal("static")) - Expect(kubeletConfig.CPUManagerReconcilePeriod.Seconds()).To(Equal(5)) + Expect(kubeletConfig.CPUManagerReconcilePeriod.Seconds()).To(BeNumerically("==", 5)) } }) }) @@ -138,7 +139,7 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord Name: components.GetComponentName(profile.Name, components.ComponentNamePrefix), Namespace: metav1.NamespaceNone, } - err := testclient.ControlPlaneClient.Get(context.TODO(), configKey, &kubeletConfig) + err := testclient.ControlPlaneClient.Get(ctx, configKey, &kubeletConfig) if err != nil { klog.Warningf("Failed to get the KubeletConfig %q", configKey.Name) } @@ -149,10 +150,19 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord Expect(kubeletConfigString).To(ContainSubstring(`"kubeReserved":{"memory":"768Mi"}`)) Expect(kubeletConfigString).To(ContainSubstring(`"systemReserved":{"memory":"300Mi"}`)) - for _, node := range workerRTNodes { - kubeletConfig, err := nodes.GetKubeletConfig(context.TODO(), &node) + // Re-fetch nodes to get current allocatable and capacity after + // the tuning update, since workerRTNodes was populated before the + // annotation was applied and its Status values are stale. + updatedNodes, err := nodes.GetByLabels(testutils.NodeSelectorLabels) + Expect(err).ToNot(HaveOccurred()) + updatedNodes, err = nodes.MatchingOptionalSelector(updatedNodes) + Expect(err).ToNot(HaveOccurred()) + Expect(updatedNodes).ToNot(BeEmpty(), "no RT worker nodes found after update") + + for _, node := range updatedNodes { + kubeletConfig, err := nodes.GetKubeletConfig(ctx, &node) Expect(err).ToNot(HaveOccurred()) - totalCapactity := node.Status.Capacity.Memory().MilliValue() + totalCapacity := node.Status.Capacity.Memory().MilliValue() evictionMemory := kubeletConfig.EvictionHard["memory.available"] kubeReserved := kubeletConfig.KubeReserved["memory"] evictionMemoryInt, err := strconv.ParseInt(strings.TrimSuffix(evictionMemory, "Mi"), 10, 64) @@ -163,16 +173,27 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord kubeReservedMemoryResource := resource.NewQuantity(kubeReservedMemoryInt*1024*1024, resource.BinarySI) evictionMemoryResource := resource.NewQuantity(evictionMemoryInt*1024*1024, resource.BinarySI) totalKubeMemory := systemReservedResource.MilliValue() + kubeReservedMemoryResource.MilliValue() + evictionMemoryResource.MilliValue() - calculatedAllocatable := totalCapactity - totalKubeMemory + + // Pre-allocated hugepages are subtracted from allocatable memory by the + // kubelet but are still included in node capacity. The standard formula + // Allocatable = Capacity - kubeReserved - systemReserved - evictionHard + // does not account for this, so we must subtract hugepages to match the + // actual allocatable reported by the node. + var totalHugepages int64 + for resourceName, quantity := range node.Status.Capacity { + if strings.HasPrefix(string(resourceName), corev1.ResourceHugePagesPrefix) { + totalHugepages += quantity.MilliValue() + } + } + + calculatedAllocatable := totalCapacity - totalKubeMemory - totalHugepages currentAllocatable := node.Status.Allocatable.Memory().MilliValue() Expect(calculatedAllocatable).To(Equal(currentAllocatable)) } }) + It("[test_id:45495] Test setting PAO managed parameters", func() { - cnfNodes, err := nodes.GetByLabels(testutils.NodeSelectorLabels) - Expect(err).ToNot(HaveOccurred()) - Expect(len(cnfNodes)).To(BeNumerically(">", 0), "expected at least one node to match the selector") - isArm, err := infrastructure.IsARM(ctx, &cnfNodes[0]) + isArm, err := infrastructure.IsARM(ctx, &workerRTNodes[0]) Expect(err).ToNot(HaveOccurred()) if isArm { Skip("Changing topologyManagerPolicy is not supported on ARM architecture") @@ -200,7 +221,7 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord profilesupdate.WaitForTuningUpdated(ctx, profile) } for _, node := range workerRTNodes { - kubeletConfig, err := nodes.GetKubeletConfig(context.TODO(), &node) + kubeletConfig, err := nodes.GetKubeletConfig(ctx, &node) Expect(err).ToNot(HaveOccurred()) Expect(kubeletConfig.TopologyManagerPolicy).To(Equal("single-numa-node")) } @@ -210,19 +231,23 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord By("Reverting the Profile") profiles.UpdateWithRetry(initialProfile) - kubeletArguments := []string{"/bin/bash", "-c", "ps -ef | grep kubelet | grep config"} + By(fmt.Sprintf("Waiting for %s to be updated after revert", poolName)) + profilesupdate.WaitForTuningUpdated(ctx, initialProfile) + for _, node := range workerRTNodes { - kubeletConfig, err := nodes.GetKubeletConfig(context.TODO(), &node) + kubeletConfig, err := nodes.GetKubeletConfig(ctx, &node) Expect(err).ToNot(HaveOccurred()) - Expect(kubeletConfig.AllowedUnsafeSysctls).To(Equal(nil)) + Expect(kubeletConfig.AllowedUnsafeSysctls).To(BeEmpty()) Expect(kubeletConfig.KubeReserved["memory"]).ToNot(Equal("768Mi")) Expect(kubeletConfig.ImageMinimumGCAge.Seconds()).ToNot(Equal(180)) } + + autoSizingCmd := []string{"cat", "/rootfs/etc/openshift/kubelet.conf.d/20-auto-sizing.conf"} for _, node := range workerRTNodes { - out, err := nodes.ExecCommand(context.TODO(), &node, kubeletArguments) + out, err := nodes.ExecCommand(ctx, &node, autoSizingCmd) Expect(err).ToNot(HaveOccurred()) stdout := testutils.ToString(out) - Expect(strings.Contains(stdout, "300Mi")).To(BeTrue()) + Expect(stdout).ToNot(ContainSubstring("300Mi")) } }) @@ -230,16 +255,11 @@ var _ = Describe("[ref_id: 45487][performance]additional kubelet arguments", Ord By("Reverting the Profile") profile, err := profiles.GetByNodeLabels(testutils.NodeSelectorLabels) Expect(err).ToNot(HaveOccurred()) - // revert only if the profile changes. if !equality.Semantic.DeepEqual(profile.Spec, initialProfile.Spec) || !equality.Semantic.DeepEqual(profile.Annotations, initialProfile.Annotations) { profiles.UpdateWithRetry(initialProfile) - By(fmt.Sprintf("Applying changes in performance profile and waiting until %s will start updating", poolName)) - profilesupdate.WaitForTuningUpdating(ctx, initialProfile) - - By(fmt.Sprintf("Waiting when %s finishes updates", poolName)) + By(fmt.Sprintf("Waiting for %s to be updated after revert", poolName)) profilesupdate.WaitForTuningUpdated(ctx, initialProfile) - } })