pkg/scheduler/api/unschedule_info.go (83 lines of code) (raw):
package api
import (
"fmt"
"sort"
"strings"
)
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"
)
// These are reasons for a pod's transition to a condition.
const (
// PodReasonUnschedulable reason in PodScheduled PodCondition means that the scheduler
// can't schedule the pod right now, for example due to insufficient resources in the cluster.
PodReasonUnschedulable = "Unschedulable"
// PodReasonSchedulable reason in PodScheduled PodCondition means that the scheduler
// can schedule the pod right now, but not bind yet
PodReasonSchedulable = "Schedulable"
)
// 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 {
if f.err == "" {
f.err = AllNodeUnavailableMsg
}
if len(f.nodes) == 0 {
return f.err
}
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
}
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
}
// 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, ", "))
}