* Copyright (c) 2024 China Unicom Digital Technology Co., Ltd.
* openFuyao is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: hongchi hu
* Date: 2025-5-25
*/
package pod
import (
"fmt"
"reflect"
"strings"
"k8s.io/api/core/v1"
"k8s.io/klog/v2"
"openfuyao.com/colocation-management/pkg/common"
)
type baseQoSMutator struct{}
func (m *baseQoSMutator) ensurePriorityClass(pod *v1.Pod) error {
annotations := pod.GetAnnotations()
if annotations == nil {
return fmt.Errorf("pod annotations are nil")
}
qosLevel, ok := annotations[common.QosClassAnnotationKey]
if !ok {
klog.Info("qoS level annotation not found in pod")
return fmt.Errorf("qoS level annotation not found")
}
if pod.Spec.PriorityClassName != "" {
existingLevel := strings.TrimPrefix(pod.Spec.PriorityClassName, "priority-")
if existingLevel != strings.ToLower(qosLevel) {
return fmt.Errorf("existing PriorityClassName conflicts with QoS level (current: %s, expected: %s)",
existingLevel, strings.ToLower(qosLevel))
}
return nil
}
if err := m.cleanupPriorityField(pod); err != nil {
return fmt.Errorf("failed to clean up priority fields: %w", err)
}
pod.Spec.PriorityClassName = "priority-" + strings.ToLower(qosLevel)
klog.Infof("Setting PriorityClassName to %s for pod %s", pod.Spec.PriorityClassName, pod.Name)
return nil
}
func (m *baseQoSMutator) cleanupPriorityField(pod *v1.Pod) error {
priorityField := reflect.ValueOf(&pod.Spec).Elem().FieldByName("Priority")
if !priorityField.IsValid() {
return nil
}
if !priorityField.IsNil() && !priorityField.IsZero() {
klog.InfoS("Clearing deprecated priority field",
"pod", klog.KObj(pod),
"previousPriority", priorityField.Elem().Int())
priorityField.Set(reflect.Zero(priorityField.Type()))
}
return nil
}
type hlsQoSMutator struct {
baseQoSMutator
}
func (m *hlsQoSMutator) MutatePod(pod *v1.Pod) (bool, error) {
if err := m.ensurePriorityClass(pod); err != nil {
klog.Infof("Failed to ensure priority class for HLS pod %s/%s: %v", pod.Namespace, pod.Name, err)
return false, fmt.Errorf("pod priority class error: %v", err)
}
klog.Infof("Finish setting PriorityClassName for hls pod")
return true, nil
}
func NewHLSPodQoSMutator() *hlsQoSMutator {
return &hlsQoSMutator{}
}
type lsQoSMutator struct {
baseQoSMutator
}
func (m *lsQoSMutator) MutatePod(pod *v1.Pod) (bool, error) {
if err := m.ensurePriorityClass(pod); err != nil {
klog.Infof("Failed to ensure priority class for LS pod %s/%s: %v", pod.Namespace, pod.Name, err)
return false, fmt.Errorf("LS pod priority class error: %v", err)
}
m.addRubikQuotaTurboAnnotation(pod)
return true, nil
}
func (m *lsQoSMutator) addRubikQuotaTurboAnnotation(pod *v1.Pod) {
defer func() {
if r := recover(); r != nil {
klog.Warningf("Panic while adding rubik quota-turbo annotation to LS pod %s/%s: %v", pod.Namespace, pod.Name, r)
}
}()
if pod.Annotations == nil {
pod.Annotations = make(map[string]string)
}
pod.Annotations[common.RubikQuotaTurboAnnotation] = "true"
klog.Infof("Successfully added quota-turbo annotation to LS pod %s/%s", pod.Namespace, pod.Name)
}
func NewLSPodQoSMutator() *lsQoSMutator {
return &lsQoSMutator{}
}
type beQoSMutator struct {
baseQoSMutator
}
func (m *beQoSMutator) MutatePod(pod *v1.Pod) (bool, error) {
if err := m.ensurePriorityClass(pod); err != nil {
klog.Infof("Failed to ensure priority class for BE pod %s/%s: %v", pod.Namespace, pod.Name, err)
return false, fmt.Errorf("LS pod priority class error: %v", err)
}
return true, nil
}
func NewBEPodQoSMutator() *beQoSMutator {
return &beQoSMutator{}
}