forked from volcano-sh/volcano
/
unschedule_info.go
112 lines (96 loc) · 2.72 KB
/
unschedule_info.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package api
import (
"fmt"
"sort"
"strings"
"k8s.io/kubernetes/pkg/scheduler/algorithm"
)
const (
// NodePodNumberExceeded means pods in node exceed the allocatable pod number
NodePodNumberExceeded = "node(s) pod number exceeded"
// NodeResourceFitFailed means node could not fit the request of pod
NodeResourceFitFailed = "node(s) resource fit failed"
// AllNodeUnavailableMsg is the default error message
AllNodeUnavailableMsg = "all nodes are unavailable"
)
// FitErrors is set of FitError on many nodes
type FitErrors struct {
nodes map[string]*FitError
err string
}
// NewFitErrors returns an FitErrors
func NewFitErrors() *FitErrors {
f := new(FitErrors)
f.nodes = make(map[string]*FitError)
return f
}
// SetError set the common error message in FitErrors
func (f *FitErrors) SetError(err string) {
f.err = err
}
// SetNodeError set the node error in FitErrors
func (f *FitErrors) SetNodeError(nodeName string, err error) {
var fe *FitError
switch obj := err.(type) {
case *FitError:
obj.NodeName = nodeName
fe = obj
default:
fe = &FitError{
NodeName: nodeName,
Reasons: []string{obj.Error()},
}
}
f.nodes[nodeName] = fe
}
// Error returns the final error message
func (f *FitErrors) Error() string {
reasons := make(map[string]int)
for _, node := range f.nodes {
for _, reason := range node.Reasons {
reasons[reason]++
}
}
sortReasonsHistogram := func() []string {
reasonStrings := []string{}
for k, v := range reasons {
reasonStrings = append(reasonStrings, fmt.Sprintf("%v %v", v, k))
}
sort.Strings(reasonStrings)
return reasonStrings
}
if f.err == "" {
f.err = AllNodeUnavailableMsg
}
reasonMsg := fmt.Sprintf(f.err+": %v.", strings.Join(sortReasonsHistogram(), ", "))
return reasonMsg
}
// FitError describe the reason why task could not fit that node
type FitError struct {
taskNamespace string
taskName string
NodeName string
Reasons []string
}
// NewFitError return FitError by message
func NewFitError(task *TaskInfo, node *NodeInfo, message ...string) *FitError {
fe := &FitError{
taskName: task.Name,
taskNamespace: task.Namespace,
NodeName: node.Name,
Reasons: message,
}
return fe
}
// NewFitErrorByReasons return FitError by reasons
func NewFitErrorByReasons(task *TaskInfo, node *NodeInfo, reasons ...algorithm.PredicateFailureReason) *FitError {
message := make([]string, 0, len(reasons))
for _, reason := range reasons {
message = append(message, reason.GetReason())
}
return NewFitError(task, node, message...)
}
// Error returns the final error message
func (f *FitError) Error() string {
return fmt.Sprintf("task %s/%s on node %s fit failed: %s", f.taskNamespace, f.taskName, f.NodeName, strings.Join(f.Reasons, ", "))
}