@@ -43,6 +43,10 @@ const (
4343 cdiDeviceKey = "cdi-devices.noderesource.dev"
4444 // Deprecated: Prefix of the key used for CDI device annotations.
4545 oldCDIDeviceKey = "cdi-devices.nri.io"
46+ // Prefix of the key used for scheduler attribute adjustment.
47+ schedulerKey = "scheduling-policy.noderesource.dev"
48+ // Deprecated: Prefix of the key used for scheduler attribute adjustment.
49+ oldSchedulerKey = "scheduling-policy.nri.io"
4650)
4751
4852var (
@@ -69,6 +73,17 @@ type mount struct {
6973 Options []string `json:"options"`
7074}
7175
76+ // scheduler attribute adjustment
77+ type scheduler struct {
78+ Policy string `json:"policy"`
79+ Nice int32 `json:"nice"`
80+ Priority int32 `json:"priority"`
81+ Flags []string `json:"flags"`
82+ Runtime uint64 `json:"runtime"`
83+ Deadline uint64 `json:"deadline"`
84+ Period uint64 `json:"period"`
85+ }
86+
7287// our injector plugin
7388type plugin struct {
7489 stub stub.Stub
@@ -94,6 +109,10 @@ func (p *plugin) CreateContainer(_ context.Context, pod *api.PodSandbox, ctr *ap
94109 return nil , nil , err
95110 }
96111
112+ if err := adjustScheduler (pod , ctr , adjust ); err != nil {
113+ return nil , nil , err
114+ }
115+
97116 if verbose {
98117 dump (containerName (pod , ctr ), "ContainerAdjustment" , adjust )
99118 }
@@ -232,6 +251,46 @@ func parseMounts(ctr string, annotations map[string]string) ([]mount, error) {
232251 return mounts , nil
233252}
234253
254+ func adjustScheduler (pod * api.PodSandbox , ctr * api.Container , a * api.ContainerAdjustment ) error {
255+ sch , err := parseScheduler (ctr .Name , pod .Annotations )
256+ if err != nil {
257+ return err
258+ }
259+
260+ if sch == nil {
261+ log .Debugf ("%s: no scheduling attributes annotated..." , containerName (pod , ctr ))
262+ return nil
263+ }
264+
265+ if verbose {
266+ dump (containerName (pod , ctr ), "annotated scheduling attributes" , sch )
267+ }
268+
269+ a .SetLinuxScheduler (sch .ToNRI ())
270+ if ! verbose {
271+ log .Infof ("%s: adjusted scheduling attributes to %s..." , containerName (pod , ctr ), sch )
272+ }
273+
274+ return nil
275+ }
276+
277+ func parseScheduler (ctr string , annotations map [string ]string ) (* scheduler , error ) {
278+ var (
279+ sch = & scheduler {}
280+ )
281+
282+ annotation := getAnnotation (annotations , schedulerKey , oldSchedulerKey , ctr )
283+ if annotation == nil {
284+ return nil , nil
285+ }
286+
287+ if err := yaml .Unmarshal (annotation , sch ); err != nil {
288+ return nil , fmt .Errorf ("invalid scheduler annotation %q: %w" , string (annotation ), err )
289+ }
290+
291+ return sch , nil
292+ }
293+
235294func getAnnotation (annotations map [string ]string , mainKey , oldKey , ctr string ) []byte {
236295 for _ , key := range []string {
237296 mainKey + "/container." + ctr ,
@@ -280,6 +339,47 @@ func (m *mount) toNRI() *api.Mount {
280339 return apiMnt
281340}
282341
342+ // Convert scheduling attributes to the NRI API representation.
343+ func (sch * scheduler ) ToNRI () * api.LinuxScheduler {
344+ apiSch := & api.LinuxScheduler {
345+ Policy : api .LinuxSchedulerPolicy (api .LinuxSchedulerPolicy_value [sch .Policy ]),
346+ Nice : sch .Nice ,
347+ Priority : sch .Priority ,
348+ Runtime : sch .Runtime ,
349+ Deadline : sch .Deadline ,
350+ Period : sch .Period ,
351+ }
352+
353+ for _ , f := range sch .Flags {
354+ apiSch .Flags = append (apiSch .Flags , api .LinuxSchedulerFlag (api .LinuxSchedulerFlag_value [f ]))
355+ }
356+
357+ return apiSch
358+ }
359+
360+ func (sc * scheduler ) String () string {
361+ if sc == nil {
362+ return "<no scheduling attributes>"
363+ }
364+
365+ s := fmt .Sprintf ("<scheduler policy=%s" , sc .Policy )
366+ if sc .Nice != 0 {
367+ s += fmt .Sprintf (", nice=%d" , sc .Nice )
368+ }
369+ if sc .Priority != 0 {
370+ s += fmt .Sprintf (", priority=%d" , sc .Priority )
371+ }
372+ if sc .Runtime != 0 {
373+ s += fmt .Sprintf (", runtime=%d, deadline=%d, period=%d" , sc .Runtime , sc .Deadline , sc .Period )
374+ }
375+ if len (sc .Flags ) > 0 {
376+ s += fmt .Sprintf (", flags=%v" , sc .Flags )
377+ }
378+ s += ">"
379+
380+ return s
381+ }
382+
283383// Construct a container name for log messages.
284384func containerName (pod * api.PodSandbox , container * api.Container ) string {
285385 if pod != nil {
0 commit comments