@@ -51,6 +51,10 @@ const (
5151 netDeviceKey = "network-devices.noderesource.dev"
5252 // Deprecated: Prefix of the key used for network device injection.
5353 oldNetDeviceKey = "network-devices.nri.io"
54+ // Prefix of the key used for scheduler attribute adjustment.
55+ schedulerKey = "scheduling-policy.noderesource.dev"
56+ // Deprecated: Prefix of the key used for scheduler attribute adjustment.
57+ oldSchedulerKey = "scheduling-policy.nri.io"
5458)
5559
5660var (
@@ -89,6 +93,17 @@ type netDevice struct {
8993 Name string `json:"name"`
9094}
9195
96+ // scheduler attribute adjustment
97+ type scheduler struct {
98+ Policy string `json:"policy"`
99+ Nice int32 `json:"nice"`
100+ Priority int32 `json:"priority"`
101+ Flags []string `json:"flags"`
102+ Runtime uint64 `json:"runtime"`
103+ Deadline uint64 `json:"deadline"`
104+ Period uint64 `json:"period"`
105+ }
106+
92107// our injector plugin
93108type plugin struct {
94109 stub stub.Stub
@@ -117,6 +132,9 @@ func (p *plugin) CreateContainer(_ context.Context, pod *api.PodSandbox, ctr *ap
117132 if err := setIOPriority (pod , ctr , adjust ); err != nil {
118133 return nil , nil , err
119134 }
135+ if err := adjustScheduler (pod , ctr , adjust ); err != nil {
136+ return nil , nil , err
137+ }
120138
121139 if err := injectNetDevices (pod , ctr , adjust ); err != nil {
122140 return nil , nil , err
@@ -275,6 +293,29 @@ func setIOPriority(pod *api.PodSandbox, ctr *api.Container, a *api.ContainerAdju
275293 return nil
276294}
277295
296+ func adjustScheduler (pod * api.PodSandbox , ctr * api.Container , a * api.ContainerAdjustment ) error {
297+ sch , err := parseScheduler (ctr .Name , pod .Annotations )
298+ if err != nil {
299+ return err
300+ }
301+
302+ if sch == nil {
303+ log .Debugf ("%s: no scheduling attributes annotated..." , containerName (pod , ctr ))
304+ return nil
305+ }
306+
307+ if verbose {
308+ dump (containerName (pod , ctr ), "annotated scheduling attributes" , sch )
309+ }
310+
311+ a .SetLinuxScheduler (sch .ToNRI ())
312+ if ! verbose {
313+ log .Infof ("%s: adjusted scheduling attributes to %s..." , containerName (pod , ctr ), sch )
314+ }
315+
316+ return nil
317+ }
318+
278319func parseIOPriority (ctr string , annotations map [string ]string ) (* ioPrio , error ) {
279320 var (
280321 priority = & ioPrio {}
@@ -337,6 +378,23 @@ func parseNetDevices(ctr string, annotations map[string]string) ([]*netDevice, e
337378 return devices , nil
338379}
339380
381+ func parseScheduler (ctr string , annotations map [string ]string ) (* scheduler , error ) {
382+ var (
383+ sch = & scheduler {}
384+ )
385+
386+ annotation := getAnnotation (annotations , schedulerKey , oldSchedulerKey , ctr )
387+ if annotation == nil {
388+ return nil , nil
389+ }
390+
391+ if err := yaml .Unmarshal (annotation , sch ); err != nil {
392+ return nil , fmt .Errorf ("invalid scheduler annotation %q: %w" , string (annotation ), err )
393+ }
394+
395+ return sch , nil
396+ }
397+
340398func getAnnotation (annotations map [string ]string , mainKey , oldKey , ctr string ) []byte {
341399 for _ , key := range []string {
342400 mainKey + "/container." + ctr ,
@@ -420,6 +478,47 @@ func (p *ioPrio) String() string {
420478 return fmt .Sprintf ("<I/O priority class %s:%d>" , p .Class , p .Priority )
421479}
422480
481+ // Convert scheduling attributes to the NRI API representation.
482+ func (sch * scheduler ) ToNRI () * api.LinuxScheduler {
483+ apiSch := & api.LinuxScheduler {
484+ Policy : api .LinuxSchedulerPolicy (api .LinuxSchedulerPolicy_value [sch .Policy ]),
485+ Nice : sch .Nice ,
486+ Priority : sch .Priority ,
487+ Runtime : sch .Runtime ,
488+ Deadline : sch .Deadline ,
489+ Period : sch .Period ,
490+ }
491+
492+ for _ , f := range sch .Flags {
493+ apiSch .Flags = append (apiSch .Flags , api .LinuxSchedulerFlag (api .LinuxSchedulerFlag_value [f ]))
494+ }
495+
496+ return apiSch
497+ }
498+
499+ func (sc * scheduler ) String () string {
500+ if sc == nil {
501+ return "<no scheduling attributes>"
502+ }
503+
504+ s := fmt .Sprintf ("<scheduler policy=%s" , sc .Policy )
505+ if sc .Nice != 0 {
506+ s += fmt .Sprintf (", nice=%d" , sc .Nice )
507+ }
508+ if sc .Priority != 0 {
509+ s += fmt .Sprintf (", priority=%d" , sc .Priority )
510+ }
511+ if sc .Runtime != 0 {
512+ s += fmt .Sprintf (", runtime=%d, deadline=%d, period=%d" , sc .Runtime , sc .Deadline , sc .Period )
513+ }
514+ if len (sc .Flags ) > 0 {
515+ s += fmt .Sprintf (", flags=%v" , sc .Flags )
516+ }
517+ s += ">"
518+
519+ return s
520+ }
521+
423522// Construct a container name for log messages.
424523func containerName (pod * api.PodSandbox , container * api.Container ) string {
425524 if pod != nil {
0 commit comments