@@ -55,13 +55,16 @@ import (
5555 "github.com/openshift-kni/numaresources-operator/pkg/validation"
5656 rteconfig "github.com/openshift-kni/numaresources-operator/rte/pkg/config"
5757 "github.com/openshift-kni/numaresources-operator/test/e2e/label"
58+ e2eclient "github.com/openshift-kni/numaresources-operator/test/internal/clients"
5859 "github.com/openshift-kni/numaresources-operator/test/internal/configuration"
5960 e2efixture "github.com/openshift-kni/numaresources-operator/test/internal/fixture"
6061 e2enrt "github.com/openshift-kni/numaresources-operator/test/internal/noderesourcetopologies"
6162 "github.com/openshift-kni/numaresources-operator/test/internal/nrosched"
6263 "github.com/openshift-kni/numaresources-operator/test/internal/objects"
6364
6465 serialconfig "github.com/openshift-kni/numaresources-operator/test/e2e/serial/config"
66+ "github.com/openshift-kni/numaresources-operator/test/internal/hypershift"
67+ "github.com/openshift-kni/numaresources-operator/test/internal/nodepools"
6568)
6669
6770/*
@@ -83,6 +86,14 @@ type mcpInfo struct {
8386 sampleNode corev1.Node
8487}
8588
89+ type Tuning struct {
90+ Profile struct {
91+ CPU struct {
92+ TopologyManagerPolicy string `yaml:"topologyManagerPolicy"`
93+ } `yaml:"cpu"`
94+ } `yaml:"profile"`
95+ }
96+
8697func (i mcpInfo ) ToString () string {
8798 mcpname := ""
8899 if i .mcpObj != nil {
@@ -285,6 +296,90 @@ var _ = Describe("[serial][disruptive] numaresources configuration management",
285296 Expect (schedOK ).To (BeTrue (), "pod %s/%s not scheduled with expected scheduler %s" , updatedPod .Namespace , updatedPod .Name , serialconfig .SchedulerTestName )
286297 })
287298
299+ It ("[test_id:80821] Verify Performance Profile updates on management cluster reflect in NRT resources" , Label ("reboot_required" , label .Slow , label .HyperShift ), func () {
300+ fxt .IsRebootTest = true
301+
302+ By ("fetching the initial TM policy set in NRT" )
303+ initialNrtList := nrtv1alpha2.NodeResourceTopologyList {}
304+ initialNrtList , err := e2enrt .GetUpdated (fxt .Client , initialNrtList , timeout )
305+ Expect (err ).ToNot (HaveOccurred (), "cannot get any NodeResourceTopology object from the cluster" )
306+ Expect (initialNrtList .Items ).ToNot (BeEmpty (), "no NodeResourceTopology items found" )
307+
308+ initialNrt := initialNrtList .Items [0 ]
309+ var initialTMPolicy string
310+ for _ , attr := range initialNrt .Attributes {
311+ if attr .Name == "topologyManagerPolicy" {
312+ initialTMPolicy = attr .Value
313+ break
314+ }
315+ }
316+ Expect (initialTMPolicy ).ToNot (BeEmpty (), "topologyManagerPolicy not found in initial NRT" )
317+ newTMPolicy := getNewTopologyManagerPolicyValue (initialTMPolicy )
318+ Expect (initialTMPolicy ).ToNot (Equal (newTMPolicy ), "new TM policy should differ from the initial one" )
319+
320+ By ("retrieving the PerformanceProfile configmap from the management cluster" )
321+ hostedClusterName , err := hypershift .GetHostedClusterName ()
322+ Expect (err ).ToNot (HaveOccurred ())
323+ nodePool , err := nodepools .GetByClusterName (context .TODO (), e2eclient .MNGClient , hostedClusterName )
324+ Expect (err ).ToNot (HaveOccurred ())
325+
326+ By ("validating the tuningConfig name against ConfigMaps in the management cluster" )
327+ tuningConfigName := nodePool .Spec .TuningConfig [0 ].Name
328+ Expect (tuningConfigName ).ToNot (BeEmpty (), "NodePool tuningConfig name is empty" )
329+
330+ cmList := & corev1.ConfigMapList {}
331+ err = e2eclient .MNGClient .List (context .TODO (), cmList , & client.ListOptions {
332+ Namespace : "clusters" ,
333+ })
334+ Expect (err ).ToNot (HaveOccurred (), "failed to list ConfigMaps in namespace: clusters" )
335+
336+ var targetCM * corev1.ConfigMap
337+ for i := range cmList .Items {
338+ if cmList .Items [i ].Name == tuningConfigName {
339+ targetCM = & cmList .Items [i ]
340+ break
341+ }
342+ }
343+ Expect (targetCM ).ToNot (BeNil (), fmt .Sprintf ("ConfigMap %q not found in namespace: clusters" , tuningConfigName ))
344+
345+ By ("updating the ConfigMap with the new TM policy" )
346+ yamlData := targetCM .Data ["tuning" ]
347+ Expect (yamlData ).ToNot (BeEmpty (), "tuning section not found in ConfigMap" )
348+
349+ var tuning Tuning
350+ err = yaml .Unmarshal ([]byte (yamlData ), & tuning )
351+ Expect (err ).ToNot (HaveOccurred (), "failed to unmarshal ConfigMap tuning YAML" )
352+ Expect (tuning .Profile .CPU .TopologyManagerPolicy ).To (Equal (initialTMPolicy ), "unexpected initial TM policy in parsed YAML" )
353+
354+ tuning .Profile .CPU .TopologyManagerPolicy = newTMPolicy
355+
356+ modifiedYamlBytes , err := yaml .Marshal (& tuning )
357+ Expect (err ).ToNot (HaveOccurred (), "failed to marshal modified tuning YAML" )
358+ modifiedYaml := string (modifiedYamlBytes )
359+ Expect (modifiedYaml ).ToNot (Equal (yamlData ), "no changes applied to ConfigMap YAML" )
360+
361+ targetCM .Data ["tuning" ] = modifiedYaml
362+ err = e2eclient .MNGClient .Update (context .TODO (), targetCM )
363+ Expect (err ).ToNot (HaveOccurred (), "failed to update the ConfigMap with new TM policy" )
364+
365+ By ("waiting for the NRT to reflect the new TM policy" )
366+ Eventually (func (g Gomega ) {
367+ updatedNrtList := nrtv1alpha2.NodeResourceTopologyList {}
368+ updatedNrtList , err = e2enrt .GetUpdated (fxt .Client , updatedNrtList , timeout )
369+ g .Expect (err ).ToNot (HaveOccurred ())
370+ g .Expect (updatedNrtList .Items ).ToNot (BeEmpty ())
371+
372+ var updatedTM string
373+ for _ , attr := range updatedNrtList .Items [0 ].Attributes {
374+ if attr .Name == "topologyManagerPolicy" {
375+ updatedTM = attr .Value
376+ break
377+ }
378+ }
379+ g .Expect (updatedTM ).To (Equal (newTMPolicy ), "Expected updated TM policy %q, but got %q" , newTMPolicy , updatedTM )
380+ }, 10 * time .Minute , 25 * time .Second ).Should (Succeed (), "NRT did not reflect updated TM policy in time" )
381+ })
382+
288383 It ("should report the NodeGroupConfig in the status" , Label ("tier2" , "openshift" ), func () {
289384 nroKey := objects .NROObjectKey ()
290385 nroOperObj := nropv1.NUMAResourcesOperator {}
@@ -732,6 +827,14 @@ func objRefListToStringList(objRefs []configv1.ObjectReference) []string {
732827 return ret
733828}
734829
830+ func getNewTopologyManagerPolicyValue (oldTopologyManagerPolicyValue string ) string {
831+ newTopologyManagerPolicyValue := "best-effort"
832+ if oldTopologyManagerPolicyValue == newTopologyManagerPolicyValue || oldTopologyManagerPolicyValue == "" {
833+ newTopologyManagerPolicyValue = "single-numa-node"
834+ }
835+ return newTopologyManagerPolicyValue
836+ }
837+
735838func toJSON (obj interface {}) string {
736839 data , err := json .Marshal (obj )
737840 if err != nil {
0 commit comments