@@ -55,6 +55,10 @@ const (
5555 schedulerKey = "scheduling-policy.noderesource.dev"
5656 // Deprecated: Prefix of the key used for scheduler attribute adjustment.
5757 oldSchedulerKey = "scheduling-policy.nri.io"
58+ // Prefix of the key used for memory policy adjustment.
59+ memoryPolicyKey = "memory-policy.noderesource.dev"
60+ // Deprecated: Prefix of the key used for memory policy adjustment.
61+ oldMemoryPolicyKey = "memory-policy.nri.io"
5862)
5963
6064var (
@@ -104,6 +108,13 @@ type scheduler struct {
104108 Period uint64 `json:"period"`
105109}
106110
111+ // memoryPolicy adjustment
112+ type memoryPolicy struct {
113+ Mode string `json:"mode"`
114+ Nodes string `json:"nodes"`
115+ Flags []string `json:"flags"`
116+ }
117+
107118// our injector plugin
108119type plugin struct {
109120 stub stub.Stub
@@ -135,6 +146,9 @@ func (p *plugin) CreateContainer(_ context.Context, pod *api.PodSandbox, ctr *ap
135146 if err := adjustScheduler (pod , ctr , adjust ); err != nil {
136147 return nil , nil , err
137148 }
149+ if err := adjustMemoryPolicy (pod , ctr , adjust ); err != nil {
150+ return nil , nil , err
151+ }
138152
139153 if err := injectNetDevices (pod , ctr , adjust ); err != nil {
140154 return nil , nil , err
@@ -395,6 +409,70 @@ func parseScheduler(ctr string, annotations map[string]string) (*scheduler, erro
395409 return sch , nil
396410}
397411
412+ func adjustMemoryPolicy (pod * api.PodSandbox , ctr * api.Container , a * api.ContainerAdjustment ) error {
413+ pol , err := parseMemoryPolicy (ctr .Name , pod .Annotations )
414+ if err != nil {
415+ log .Errorf ("%s: invalid memory policy annotation: %v" ,
416+ containerName (pod , ctr ), err )
417+ return err
418+ }
419+
420+ if pol == nil {
421+ log .Debugf ("%s: no memory policy annotated..." , containerName (pod , ctr ))
422+ return nil
423+ }
424+
425+ if verbose {
426+ dump (containerName (pod , ctr ), "annotated memory policy" , pol )
427+ }
428+
429+ amp , err := pol .ToNRI ()
430+ if err != nil {
431+ log .Errorf ("%s: invalid memory policy annotation: %v" ,
432+ containerName (pod , ctr ), err )
433+ return fmt .Errorf ("invalid memory policy: %w" , err )
434+ }
435+
436+ a .SetLinuxMemoryPolicy (amp .Mode , amp .Nodes , amp .Flags ... )
437+ if ! verbose {
438+ log .Infof ("%s: adjusted memory policy to %s..." , containerName (pod , ctr ), amp )
439+ }
440+
441+ return nil
442+ }
443+
444+ func parseMemoryPolicy (ctr string , annotations map [string ]string ) (* memoryPolicy , error ) {
445+ var (
446+ policy = & memoryPolicy {}
447+ )
448+
449+ annotation := getAnnotation (annotations , memoryPolicyKey , oldMemoryPolicyKey , ctr )
450+ if annotation == nil {
451+ return nil , nil
452+ }
453+
454+ if err := yaml .Unmarshal (annotation , policy ); err != nil {
455+ return nil , fmt .Errorf ("invalid memory policy annotation %q: %w" , string (annotation ), err )
456+ }
457+
458+ if policy .Mode != "" {
459+ policy .Mode = strings .ToUpper (policy .Mode )
460+ if ! strings .HasPrefix (policy .Mode , "MPOL_" ) {
461+ policy .Mode = "MPOL_" + policy .Mode
462+ }
463+ }
464+
465+ for i , f := range policy .Flags {
466+ f = strings .ToUpper (f )
467+ if ! strings .HasPrefix (f , "MPOL_F_" ) {
468+ f = "MPOL_F_" + f
469+ }
470+ policy .Flags [i ] = f
471+ }
472+
473+ return policy , nil
474+ }
475+
398476func getAnnotation (annotations map [string ]string , mainKey , oldKey , ctr string ) []byte {
399477 for _ , key := range []string {
400478 mainKey + "/container." + ctr ,
@@ -519,6 +597,46 @@ func (sc *scheduler) String() string {
519597 return s
520598}
521599
600+ // Convert memoryPolicy to the NRI API representation.
601+ func (mp * memoryPolicy ) ToNRI () (* api.LinuxMemoryPolicy , error ) {
602+ apiPol := & api.LinuxMemoryPolicy {
603+ Nodes : mp .Nodes ,
604+ }
605+
606+ mode , ok := api .MpolMode_value [strings .ToUpper (mp .Mode )]
607+ if ! ok {
608+ return nil , fmt .Errorf ("invalid memory policy mode %q" , mp .Mode )
609+ }
610+ apiPol .Mode = api .MpolMode (mode )
611+
612+ for _ , f := range mp .Flags {
613+ flag , ok := api .MpolFlag_value [strings .ToUpper (f )]
614+ if ! ok {
615+ return nil , fmt .Errorf ("invalid memory policy flag %q" , f )
616+ }
617+ apiPol .Flags = append (apiPol .Flags , api .MpolFlag (flag ))
618+ }
619+
620+ return apiPol , nil
621+ }
622+
623+ func (mp * memoryPolicy ) String () string {
624+ if mp == nil {
625+ return "<no memory policy>"
626+ }
627+
628+ s := fmt .Sprintf ("<memory policy mode=%s" , mp .Mode )
629+ if mp .Nodes != "" {
630+ s += fmt .Sprintf (", nodes=%s" , mp .Nodes )
631+ }
632+ if len (mp .Flags ) > 0 {
633+ s += fmt .Sprintf (", flags=%v" , mp .Flags )
634+ }
635+ s += ">"
636+
637+ return s
638+ }
639+
522640// Construct a container name for log messages.
523641func containerName (pod * api.PodSandbox , container * api.Container ) string {
524642 if pod != nil {
0 commit comments