volcano.sh/volcano@v1.9.0/pkg/scheduler/api/unschedule_info.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 ) 8 9 const ( 10 // NodePodNumberExceeded means pods in node exceed the allocatable pod number 11 NodePodNumberExceeded = "node(s) pod number exceeded" 12 // NodeResourceFitFailed means node could not fit the request of pod 13 NodeResourceFitFailed = "node(s) resource fit failed" 14 15 // AllNodeUnavailableMsg is the default error message 16 AllNodeUnavailableMsg = "all nodes are unavailable" 17 ) 18 19 // These are reasons for a pod's transition to a condition. 20 const ( 21 // PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler 22 // can't schedule the pod right now, for example due to insufficient resources in the cluster. 23 // It can also mean that the scheduler skips scheduling the pod which left the pod `Undetermined`, 24 // for example due to unschedulable pod already occurred. 25 PodReasonUnschedulable = "Unschedulable" 26 // PodReasonSchedulable reason in PodScheduled PodCondition means that the scheduler 27 // can schedule the pod right now, but not bind yet 28 PodReasonSchedulable = "Schedulable" 29 ) 30 31 // FitErrors is set of FitError on many nodes 32 type FitErrors struct { 33 nodes map[string]*FitError 34 err string 35 } 36 37 // NewFitErrors returns an FitErrors 38 func NewFitErrors() *FitErrors { 39 f := new(FitErrors) 40 f.nodes = make(map[string]*FitError) 41 return f 42 } 43 44 // SetError set the common error message in FitErrors 45 func (f *FitErrors) SetError(err string) { 46 f.err = err 47 } 48 49 // SetNodeError set the node error in FitErrors 50 func (f *FitErrors) SetNodeError(nodeName string, err error) { 51 var fe *FitError 52 switch obj := err.(type) { 53 case *FitError: 54 obj.NodeName = nodeName 55 fe = obj 56 default: 57 fe = &FitError{ 58 NodeName: nodeName, 59 Reasons: []string{obj.Error()}, 60 } 61 } 62 63 f.nodes[nodeName] = fe 64 } 65 66 // Error returns the final error message 67 func (f *FitErrors) Error() string { 68 if f.err == "" { 69 f.err = fmt.Sprintf("0/%v", len(f.nodes)) + " nodes are unavailable" 70 } 71 if len(f.nodes) == 0 { 72 return f.err 73 } 74 75 reasons := make(map[string]int) 76 for _, node := range f.nodes { 77 for _, reason := range node.Reasons { 78 reasons[reason]++ 79 } 80 } 81 82 sortReasonsHistogram := func() []string { 83 reasonStrings := []string{} 84 for k, v := range reasons { 85 reasonStrings = append(reasonStrings, fmt.Sprintf("%v %v", v, k)) 86 } 87 sort.Strings(reasonStrings) 88 return reasonStrings 89 } 90 reasonMsg := fmt.Sprintf(f.err+": %v.", strings.Join(sortReasonsHistogram(), ", ")) 91 return reasonMsg 92 } 93 94 // FitError describe the reason why task could not fit that node 95 type FitError struct { 96 taskNamespace string 97 taskName string 98 NodeName string 99 Reasons []string 100 } 101 102 // NewFitError return FitError by message 103 func NewFitError(task *TaskInfo, node *NodeInfo, message ...string) *FitError { 104 fe := &FitError{ 105 taskName: task.Name, 106 taskNamespace: task.Namespace, 107 NodeName: node.Name, 108 Reasons: message, 109 } 110 return fe 111 } 112 113 // Error returns the final error message 114 func (f *FitError) Error() string { 115 return fmt.Sprintf("task %s/%s on node %s fit failed: %s", f.taskNamespace, f.taskName, f.NodeName, strings.Join(f.Reasons, ", ")) 116 } 117 118 // WrapInsufficientResourceReason wrap insufficient resource reason. 119 func WrapInsufficientResourceReason(resources []string) string { 120 if len(resources) == 0 { 121 return "" 122 } 123 return "Insufficient " + resources[0] 124 }