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  }