@@ -12,7 +12,6 @@ import (
1212
1313 appsv1 "k8s.io/api/apps/v1"
1414 corev1 "k8s.io/api/core/v1"
15- "k8s.io/apimachinery/pkg/api/errors"
1615 "k8s.io/apimachinery/pkg/api/resource"
1716 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1817 "k8s.io/apimachinery/pkg/labels"
@@ -248,7 +247,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
248247 })
249248
250249 AfterEach (func () {
251- deleteTestPod ( context .TODO (), testpod )
250+ Expect ( pods . Delete ( context .TODO (), testpod )). To ( BeTrue (), "Failed to delete pod" )
252251 })
253252
254253 DescribeTable ("Verify CPU usage by stress PODs" , func (ctx context.Context , guaranteed bool ) {
@@ -339,7 +338,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
339338 Expect (err ).ToNot (HaveOccurred ())
340339 })
341340 AfterEach (func () {
342- deleteTestPod ( context .TODO (), testpod )
341+ Expect ( pods . Delete ( context .TODO (), testpod )). To ( BeTrue (), "Failed to delete pod" )
343342 })
344343 When ("kubelet is restart" , func () {
345344 It ("[test_id: 73501] defaultCpuset should not change" , func () {
@@ -422,7 +421,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
422421
423422 AfterEach (func () {
424423 if testpod != nil {
425- deleteTestPod ( context .TODO (), testpod )
424+ Expect ( pods . Delete ( context .TODO (), testpod )). To ( BeTrue (), "Failed to delete pod" )
426425 }
427426 })
428427
@@ -481,7 +480,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
481480 fmt .Sprintf ("IRQ still active on CPU%s" , psr ))
482481
483482 By ("Checking that after removing POD default smp affinity is returned back to all active CPUs" )
484- deleteTestPod ( context .TODO (), testpod )
483+ Expect ( pods . Delete ( context .TODO (), testpod )). To ( BeTrue (), "Failed to delete pod" )
485484 defaultSmpAffinitySet , err = nodes .GetDefaultSmpAffinitySet (context .TODO (), workerRTNode )
486485 Expect (err ).ToNot (HaveOccurred ())
487486
@@ -580,7 +579,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
580579 if testpod == nil {
581580 return
582581 }
583- deleteTestPod ( context .TODO (), testpod )
582+ Expect ( pods . Delete ( context .TODO (), testpod )). To ( BeTrue (), "Failed to delete pod" )
584583 })
585584
586585 It ("[test_id:49149] should reject pods which request integral CPUs not aligned with machine SMT level" , func () {
@@ -633,7 +632,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
633632 if testpod == nil {
634633 return
635634 }
636- deleteTestPod ( context .TODO (), testpod )
635+ Expect ( pods . Delete ( context .TODO (), testpod )). To ( BeTrue (), "Failed to delete pod" )
637636 })
638637
639638 DescribeTable ("Verify Hyper-Thread aware scheduling for guaranteed pods" ,
@@ -680,7 +679,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
680679 testpod = startHTtestPod (ctx , cpuCount )
681680 Expect (checkPodHTSiblings (ctx , testpod )).To (BeTrue (), "Pod cpu set does not map to host cpu sibling pairs" )
682681 By ("Deleting test pod..." )
683- deleteTestPod ( ctx , testpod )
682+ Expect ( pods . Delete ( ctx , testpod )). To ( BeTrue (), "Failed to delete pod" )
684683 }
685684 },
686685
@@ -983,7 +982,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
983982 defer func () {
984983 if guaranteedPod != nil {
985984 testlog .Infof ("deleting pod %q" , guaranteedPod .Name )
986- deleteTestPod ( ctx , guaranteedPod )
985+ Expect ( pods . Delete ( ctx , guaranteedPod )). To ( BeTrue (), "Failed to delete guaranteed pod" )
987986 }
988987 }()
989988
@@ -1014,7 +1013,7 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
10141013 defer func () {
10151014 if bestEffortPod != nil {
10161015 testlog .Infof ("deleting pod %q" , bestEffortPod .Name )
1017- deleteTestPod ( ctx , bestEffortPod )
1016+ Expect ( pods . Delete ( ctx , bestEffortPod )). To ( BeTrue (), "Failed to delete best-effort pod" )
10181017 }
10191018 }()
10201019
@@ -1142,15 +1141,73 @@ var _ = Describe("[rfe_id:27363][performance] CPU Management", Ordered, func() {
11421141 defer func () {
11431142 if guPod != nil {
11441143 testlog .Infof ("deleting pod %q" , guPod .Name )
1145- deleteTestPod ( ctx , guPod )
1144+ Expect ( pods . Delete ( ctx , guPod )). To ( BeTrue (), "Failed to delete guaranteed pod" )
11461145 }
11471146 if buPod != nil {
11481147 testlog .Infof ("deleting pod %q" , buPod .Name )
1149- deleteTestPod ( ctx , buPod )
1148+ Expect ( pods . Delete ( ctx , buPod )). To ( BeTrue (), "Failed to delete burstable pod" )
11501149 }
11511150 }()
11521151 })
11531152 })
1153+
1154+ Context ("Check exec-cpu-affinity feature" , func () {
1155+ When ("exec-cpu-affinity is enabled (default in PP)" , func () {
1156+ // shared-cpus case is covered in 11_mixedcpus test
1157+ // legacy test is covered in 2_performance_update
1158+
1159+ BeforeEach (func () {
1160+ By ("Checking if exec-cpu-affinity is enabled by default in the profile" )
1161+ profile , _ := profiles .GetByNodeLabels (testutils .NodeSelectorLabels )
1162+ Expect (profile ).ToNot (BeNil (), "Failed to get performance profile" )
1163+ if profile .Annotations != nil {
1164+ val , ok := profile .Annotations [performancev2 .PerformanceProfileDisableExecCPUAffinityAnnotation ]
1165+ if ok && val == "true" {
1166+ // fail loadly because the default should be enabled
1167+ Fail ("exec-cpu-affinity is disabled in the profile" )
1168+ }
1169+ }
1170+ })
1171+
1172+ It ("should pin exec process to first CPU dedicated to the container - guratanteed pod" , func () {
1173+ By ("Creating a guaranteed test pod" )
1174+ testPod := makePod (ctx , workerRTNode , true )
1175+ Expect (testclient .Client .Create (ctx , testPod )).To (Succeed (), "Failed to create test pod" )
1176+ testPod , err = pods .WaitForCondition (ctx , client .ObjectKeyFromObject (testPod ), corev1 .PodReady , corev1 .ConditionTrue , 5 * time .Minute )
1177+ Expect (err ).ToNot (HaveOccurred ())
1178+ defer func () {
1179+ if testPod != nil {
1180+ testlog .Infof ("deleting pod %q" , testPod .Name )
1181+ Expect (pods .Delete (ctx , testPod )).To (BeTrue (), "Failed to delete test pod" )
1182+ }
1183+ }()
1184+
1185+ cpusetCfg := & controller.CpuSet {}
1186+ Expect (getter .Container (ctx , testPod , testPod .Spec .Containers [0 ].Name , cpusetCfg )).To (Succeed (), "Failed to get cpuset config for test pod" )
1187+
1188+ // assuming no shared cpus are used
1189+ cpusList := strings .Split (cpusetCfg .Cpus , "," )
1190+ Expect (cpusList ).ToNot (BeEmpty ())
1191+ firstExclusiveCPU := strings .TrimSpace (cpusList [0 ])
1192+ testlog .Infof ("first exclusive CPU: %s" , firstExclusiveCPU )
1193+
1194+ cpuRequest := testPod .Spec .Containers [0 ].Resources .Requests .Name (corev1 .ResourceCPU , resource .DecimalSI ).Value ()
1195+ retries := int (10 / cpuRequest )
1196+ By ("Run exec command on the pod and verify the process is pinned to the first exclusive CPU" )
1197+
1198+ for i := 0 ; i < retries ; i ++ {
1199+ cmd := []string {"/bin/bash" , "-c" , "sleep 10 & SLPID=$!; ps -o psr -p $SLPID;" }
1200+ output , err := pods .ExecCommandOnPod (testclient .K8sClient , testPod , testPod .Spec .Containers [0 ].Name , cmd )
1201+ Expect (err ).ToNot (HaveOccurred (), "Failed to exec command on the pod; retry %d" , i )
1202+ testlog .Infof ("exec command output: %s" , string (output ))
1203+
1204+ execProcessCPUs := strings .TrimSpace (string (output ))
1205+ Expect (execProcessCPUs ).ToNot (BeEmpty (), "Failed to get exec process CPU; retry %d" , i )
1206+ Expect (execProcessCPUs ).To (Equal (firstExclusiveCPU ), "Exec process CPU is not the first exclusive CPU; retry %d" , i )
1207+ }
1208+ })
1209+ })
1210+ })
11541211})
11551212
11561213func extractConfigInfo (output string ) (* ContainerConfig , error ) {
@@ -1401,24 +1458,6 @@ func getTestPodWithAnnotations(annotations map[string]string, cpus int) *corev1.
14011458 return testpod
14021459}
14031460
1404- func deleteTestPod (ctx context.Context , testpod * corev1.Pod ) (types.UID , bool ) {
1405- // it possible that the pod already was deleted as part of the test, in this case we want to skip teardown
1406- err := testclient .DataPlaneClient .Get (ctx , client .ObjectKeyFromObject (testpod ), testpod )
1407- if errors .IsNotFound (err ) {
1408- return "" , false
1409- }
1410-
1411- testpodUID := testpod .UID
1412-
1413- err = testclient .DataPlaneClient .Delete (ctx , testpod )
1414- Expect (err ).ToNot (HaveOccurred ())
1415-
1416- err = pods .WaitForDeletion (ctx , testpod , pods .DefaultDeletionTimeout * time .Second )
1417- Expect (err ).ToNot (HaveOccurred ())
1418-
1419- return testpodUID , true
1420- }
1421-
14221461func cpuSpecToString (cpus * performancev2.CPU ) (string , error ) {
14231462 if cpus == nil {
14241463 return "" , fmt .Errorf ("performance CPU field is nil" )
0 commit comments