Skip to content

Commit 698aa3b

Browse files
mrniranjanNiranjan M.R
andauthored
Adjust Workload Hints test cases based on Intel or AMD (#1277) (#1281)
* Adjust Workload Hints test cases based on Intel or AMD * Add utility function to check cpu vendor We use lscpu output and check Vendor ID to determine if the system is AMD or Intel. * Workload Hints E2E: Modify kernel args based on Vendor Adjust Workload Hints E2E test cases to verify kernel parameters depending on the Vendor in the case of x86_64 where kernel args are changed based on Intel or AMD. * Remove duplicate intel related kernel args Remove duplicate intel_pstate=passive from kernelParameters string slice as it's already added if system is intel * Add a single condition to add all kernel parameters related to intel * Minor typo fix in kernel parameter intel_idle.max.cstate=0 it should be intel_idle.max_cstate=0 --------- Signed-off-by: Niranjan M.R <[email protected]> Co-authored-by: Niranjan M.R <[email protected]>
1 parent 00135b0 commit 698aa3b

File tree

2 files changed

+165
-21
lines changed

2 files changed

+165
-21
lines changed

test/e2e/performanceprofile/functests/8_performance_workloadhints/workloadhints.go

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import (
3232
"github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/cgroup"
3333
testclient "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/client"
3434
"github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/discovery"
35+
"github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/infrastructure"
36+
"github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/label"
3537
testlog "github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/log"
3638
"github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/mcps"
3739
"github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/nodes"
@@ -45,14 +47,16 @@ const (
4547
cgroupRoot = "/rootfs/sys/fs/cgroup"
4648
)
4749

48-
var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific PerformanceProfile API", func() {
49-
var workerRTNodes []corev1.Node
50-
var profile, initialProfile *performancev2.PerformanceProfile
51-
var performanceMCP string
52-
var err error
53-
50+
var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific PerformanceProfile API", Label(string(label.WorkloadHints)), func() {
51+
var (
52+
workerRTNodes []corev1.Node
53+
profile, initialProfile *performancev2.PerformanceProfile
54+
performanceMCP string
55+
err error
56+
ctx context.Context = context.Background()
57+
isIntel, isAMD bool
58+
)
5459
nodeLabel := testutils.NodeSelectorLabels
55-
5660
BeforeEach(func() {
5761
if discovery.Enabled() && testutils.ProfileNotFound {
5862
Skip("Discovery mode enabled, performance profile not found")
@@ -65,6 +69,11 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
6569
performanceMCP, err = mcps.GetByProfile(profile)
6670
Expect(err).ToNot(HaveOccurred())
6771
klog.Infof("using performanceMCP: %q", performanceMCP)
72+
// Check if one of the nodes is intel or AMD using Vendor ID
73+
isIntel, err = infrastructure.IsIntel(ctx, &workerRTNodes[0])
74+
Expect(err).ToNot(HaveOccurred(), "Unable to fetch Vendor ID")
75+
isAMD, err = infrastructure.IsAMD(ctx, &workerRTNodes[0])
76+
Expect(err).ToNot(HaveOccurred(), "Unable to fetch Vendor ID")
6877

6978
// Verify that worker and performance MCP have updated state equals to true
7079
for _, mcpName := range []string{testutils.RoleWorker, performanceMCP} {
@@ -218,8 +227,10 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
218227
"kernel.sched_rt_runtime_us": "950000",
219228
"vm.stat_interval": "10",
220229
}
221-
kernelParameters := []string{"processor.max_cstate=1", "intel_idle.max_cstate=0"}
222-
230+
kernelParameters := []string{"processor.max_cstate=1"}
231+
if isIntel {
232+
kernelParameters = append(kernelParameters, "intel_idle.max_cstate=0")
233+
}
223234
wg := sync.WaitGroup{}
224235
By("Waiting for TuneD to start on nodes")
225236
for i := 0; i < len(workerRTNodes); i++ {
@@ -284,8 +295,7 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
284295
"vm.stat_interval": "10",
285296
}
286297
kernelParameters := []string{noHzParam, "tsc=reliable", "nosoftlockup", "nmi_watchdog=0", "mce=off", "skew_tick=1",
287-
"processor.max_cstate=1", "intel_idle.max_cstate=0", "idle=poll"}
288-
298+
"processor.max_cstate=1", "idle=poll"}
289299
wg := sync.WaitGroup{}
290300
By("Waiting for TuneD to start on nodes")
291301
for i := 0; i < len(workerRTNodes); i++ {
@@ -306,7 +316,9 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
306316
fmt.Sprintf("stalld is not running on %q when it should", node.Name))
307317

308318
By(fmt.Sprintf("Checking TuneD parameters on %q", node.Name))
309-
kernelParameters = append(kernelParameters, utilstuned.AddPstateParameter(context.TODO(), node))
319+
if isIntel {
320+
kernelParameters = append(kernelParameters, "intel_idle.max_cstate=0", utilstuned.AddPstateParameter(context.TODO(), node))
321+
}
310322
utilstuned.CheckParameters(context.TODO(), node, sysctlMap, kernelParameters, stalldEnabled, rtKernel)
311323
}()
312324
}
@@ -343,9 +355,15 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
343355
By("Verifying node kernel arguments")
344356
cmdline, err := nodes.ExecCommandOnMachineConfigDaemon(context.TODO(), &workerRTNodes[0], []string{"cat", "/proc/cmdline"})
345357
Expect(err).ToNot(HaveOccurred())
346-
Expect(cmdline).To(ContainSubstring("intel_pstate=passive"))
347-
Expect(cmdline).ToNot(ContainSubstring("intel_pstate=active"))
358+
if isIntel {
359+
Expect(cmdline).To(ContainSubstring("intel_pstate=passive"))
360+
Expect(cmdline).ToNot(ContainSubstring("intel_pstate=active"))
361+
}
348362

363+
if isAMD {
364+
Expect(cmdline).To(ContainSubstring("amd_pstate=passive"))
365+
Expect(cmdline).ToNot(ContainSubstring("amd_pstate=active"))
366+
}
349367
By("Verifying tuned profile")
350368
key := types.NamespacedName{
351369
Name: components.GetComponentName(profile.Name, components.ProfileNamePerformance),
@@ -405,7 +423,7 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
405423
"vm.stat_interval": "10",
406424
}
407425
kernelParameters := []string{noHzParam, "tsc=reliable", "nosoftlockup", "nmi_watchdog=0", "mce=off", "skew_tick=1",
408-
"processor.max_cstate=1", "intel_idle.max_cstate=0", "idle=poll"}
426+
"processor.max_cstate=1", "idle=poll"}
409427

410428
wg := sync.WaitGroup{}
411429
By("Waiting for TuneD to start on nodes")
@@ -427,7 +445,9 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
427445
fmt.Sprintf("stalld is not running on %q when it should", node.Name))
428446

429447
By(fmt.Sprintf("Checking TuneD parameters on %q", node.Name))
430-
kernelParameters = append(kernelParameters, utilstuned.AddPstateParameter(context.TODO(), node))
448+
if isIntel {
449+
kernelParameters = append(kernelParameters, "intel_idle.max_cstate=0", utilstuned.AddPstateParameter(context.TODO(), node))
450+
}
431451
utilstuned.CheckParameters(context.TODO(), node, sysctlMap, kernelParameters, stalldEnabled, rtKernel)
432452
}()
433453
}
@@ -470,8 +490,14 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
470490
"kernel.sched_rt_runtime_us": "-1",
471491
"vm.stat_interval": "10",
472492
}
473-
kernelParameters = []string{noHzParam, "tsc=reliable", "nosoftlockup", "nmi_watchdog=0", "mce=off", "skew_tick=1", "intel_pstate=passive"}
493+
kernelParameters = []string{noHzParam, "tsc=reliable", "nosoftlockup", "nmi_watchdog=0", "mce=off", "skew_tick=1"}
494+
if isIntel {
495+
kernelParameters = append(kernelParameters, "intel_pstate=passive")
496+
}
474497

498+
if isAMD {
499+
kernelParameters = append(kernelParameters, "amd_pstate=passive")
500+
}
475501
wg = sync.WaitGroup{}
476502
By("Waiting for TuneD to start on nodes")
477503
for i := 0; i < len(workerRTNodes); i++ {
@@ -542,7 +568,13 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
542568
"kernel.sched_rt_runtime_us": "-1",
543569
"vm.stat_interval": "10",
544570
}
545-
kernelParameters := []string{noHzParam, "tsc=reliable", "nosoftlockup", "nmi_watchdog=0", "mce=off", "skew_tick=1", "intel_pstate=passive"}
571+
kernelParameters := []string{noHzParam, "tsc=reliable", "nosoftlockup", "nmi_watchdog=0", "mce=off", "skew_tick=1"}
572+
if isIntel {
573+
kernelParameters = append(kernelParameters, "intel_pstate=passive")
574+
}
575+
if isAMD {
576+
kernelParameters = append(kernelParameters, "amd_pstate=passive")
577+
}
546578

547579
wg := sync.WaitGroup{}
548580
By("Waiting for TuneD to start on nodes")
@@ -607,7 +639,7 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
607639
"vm.stat_interval": "10",
608640
}
609641
kernelParameters = []string{noHzParam, "tsc=reliable", "nosoftlockup", "nmi_watchdog=0", "mce=off", "skew_tick=1",
610-
"processor.max_cstate=1", "intel_idle.max_cstate=0", "idle=poll"}
642+
"processor.max_cstate=1", "idle=poll"}
611643

612644
wg = sync.WaitGroup{}
613645
By("Waiting for TuneD to start on nodes")
@@ -629,7 +661,9 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
629661
fmt.Sprintf("stalld is not running on %q when it should", node.Name))
630662

631663
By(fmt.Sprintf("Checking TuneD parameters on %q", node.Name))
632-
kernelParameters = append(kernelParameters, utilstuned.AddPstateParameter(context.TODO(), node))
664+
if isIntel {
665+
kernelParameters = append(kernelParameters, "intel_idle.max_cstate=0", utilstuned.AddPstateParameter(context.TODO(), node))
666+
}
633667
utilstuned.CheckParameters(context.TODO(), node, sysctlMap, kernelParameters, stalldEnabled, rtKernel)
634668
}()
635669
}
@@ -658,6 +692,10 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
658692
var fullPath string = ""
659693
// This test requires real hardware with powermanagement settings done on BIOS
660694
// Using numa nodes to check if we are running on real hardware.
695+
696+
if isAMD {
697+
Skip("Crio Powersave annotations test can only be run on Intel systems")
698+
}
661699
checkHardwareCapability(context.TODO(), workerRTNodes)
662700
currentWorkloadHints := profile.Spec.WorkloadHints
663701
profile.Spec.WorkloadHints = &performancev2.WorkloadHints{
@@ -756,10 +794,13 @@ var _ = Describe("[rfe_id:49062][workloadHints] Telco friendly workload specific
756794
err = checkCpuGovernorsAndResumeLatency(context.TODO(), targetCpus, &workerRTNodes[0], "0", "performance")
757795
})
758796

759-
It("[test_id:54186] Verify sysfs paramters of guaranteed pod with performance annotiations", func() {
797+
It("[test_id:54186] Verify sysfs parameters of guaranteed pod with performance annotiations", func() {
760798

761799
// This test requires real hardware with powermanagement settings done on BIOS
762800
// Using numa nodes to check if we are running on real hardware
801+
if isAMD {
802+
Skip("Crio Powersave annotations test can only be run on Intel systems")
803+
}
763804
var containerCgroup, fullPath string
764805
checkHardwareCapability(context.TODO(), workerRTNodes)
765806
currentWorkloadHints := profile.Spec.WorkloadHints
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package infrastructure
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"github.com/openshift/cluster-node-tuning-operator/test/e2e/performanceprofile/functests/utils/nodes"
8+
corev1 "k8s.io/api/core/v1"
9+
)
10+
11+
// CpuArchitecture struct to represent CPU Details
12+
type CpuArchitecture struct {
13+
Lscpu []cpuField `json:"lscpu"`
14+
}
15+
type cpuField struct {
16+
Field string `json:"field"`
17+
Data string `json:"data"`
18+
}
19+
20+
const (
21+
IntelVendorID = "GenuineIntel"
22+
AMDVendorID = "AuthenticAMD"
23+
)
24+
25+
// lscpuPraser parses lscpu output and returns its fields in struct
26+
func lscpuPraser(ctx context.Context, node *corev1.Node) (CpuArchitecture, error) {
27+
cmd := []string{"lscpu", "-J"}
28+
var cpuinfo CpuArchitecture
29+
out, err := nodes.ExecCommandOnNode(ctx, cmd, node)
30+
if err != nil {
31+
return cpuinfo, fmt.Errorf("error executing lscpu command: %v", err)
32+
}
33+
err = json.Unmarshal([]byte(out), &cpuinfo)
34+
if err != nil {
35+
return cpuinfo, fmt.Errorf("error unmarshalling cpu info: %v", err)
36+
}
37+
return cpuinfo, nil
38+
}
39+
40+
// CPUArchitecture returns CPU Architecture from lscpu output
41+
func CPUArchitecture(ctx context.Context, node *corev1.Node) (string, error) {
42+
cpuInfo, err := lscpuPraser(ctx, node)
43+
if err != nil {
44+
return "", fmt.Errorf("Unable to parse lscpu output")
45+
}
46+
for _, v := range cpuInfo.Lscpu {
47+
if v.Field == "Architecture:" {
48+
return v.Data, nil
49+
}
50+
}
51+
return "", fmt.Errorf("could not fetch CPU architecture")
52+
}
53+
54+
// CPUVendorId returns Vendor ID information from lscpu output
55+
func CPUVendorId(ctx context.Context, node *corev1.Node) (string, error) {
56+
cpuInfo, err := lscpuPraser(ctx, node)
57+
if err != nil {
58+
return "", fmt.Errorf("Unable to parse lscpu output")
59+
}
60+
for _, v := range cpuInfo.Lscpu {
61+
if v.Field == "Vendor ID:" {
62+
return v.Data, nil
63+
}
64+
}
65+
return "", fmt.Errorf("could not fetch CPU Vendor ID")
66+
}
67+
68+
// IsCPUVendor checks if the CPU Vendor ID matches the given vendor string
69+
func IsCPUVendor(ctx context.Context, node *corev1.Node, vendor string) (bool, error) {
70+
vendorData, err := CPUVendorId(ctx, node)
71+
if err != nil {
72+
return false, err
73+
}
74+
return vendorData == vendor, nil
75+
}
76+
77+
// IsIntel returns if Vendor ID is GenuineIntel in lscpu output
78+
func IsIntel(ctx context.Context, node *corev1.Node) (bool, error) {
79+
isIntel, err := IsCPUVendor(ctx, node, IntelVendorID)
80+
if err != nil {
81+
return false, err
82+
}
83+
return isIntel, nil
84+
}
85+
86+
// IsAMD returns if Vendor ID is AuthenticAMD in lscpu output
87+
func IsAMD(ctx context.Context, node *corev1.Node) (bool, error) {
88+
isAMD, err := IsCPUVendor(ctx, node, AMDVendorID)
89+
if err != nil {
90+
return false, err
91+
}
92+
return isAMD, nil
93+
}
94+
95+
// IsARM returns if Architecture is aarch64
96+
func IsARM(ctx context.Context, node *corev1.Node) (bool, error) {
97+
architectureData, err := CPUArchitecture(ctx, node)
98+
if err != nil {
99+
return false, err
100+
}
101+
102+
return architectureData == "aarch64", nil
103+
}

0 commit comments

Comments
 (0)