-
Notifications
You must be signed in to change notification settings - Fork 582
/
interface.go
209 lines (174 loc) · 5.83 KB
/
interface.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*
Copyright 2021 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package state
import (
"context"
"errors"
"strings"
"k8s.io/apimachinery/pkg/types"
)
const (
PodFitsResources = "PodFitsResources"
NoMaxResourceCount = "NoMaxResourceCount"
EvenPodSpread = "EvenPodSpread"
AvailabilityNodePriority = "AvailabilityNodePriority"
AvailabilityZonePriority = "AvailabilityZonePriority"
LowestOrdinalPriority = "LowestOrdinalPriority"
RemoveWithEvenPodSpreadPriority = "RemoveWithEvenPodSpreadPriority"
RemoveWithAvailabilityNodePriority = "RemoveWithAvailabilityNodePriority"
RemoveWithAvailabilityZonePriority = "RemoveWithAvailabilityZonePriority"
RemoveWithHighestOrdinalPriority = "RemoveWithHighestOrdinalPriority"
)
// Plugin is the parent type for all the scheduling framework plugins.
type Plugin interface {
Name() string
}
type FilterPlugin interface {
Plugin
// Filter is called by the scheduler.
// All FilterPlugins should return "Success" to declare that
// the given pod fits the vreplica.
Filter(ctx context.Context, args interface{}, state *State, key types.NamespacedName, podID int32) *Status
}
// ScoreExtensions is an interface for Score extended functionality.
type ScoreExtensions interface {
// NormalizeScore is called for all pod scores produced by the same plugin's "Score"
// method. A successful run of NormalizeScore will update the scores list and return
// a success status.
NormalizeScore(ctx context.Context, state *State, scores PodScoreList) *Status
}
type ScorePlugin interface {
Plugin
// Score is called by the scheduler.
// All ScorePlugins should return "Success" unless the args are invalid.
Score(ctx context.Context, args interface{}, state *State, feasiblePods []int32, key types.NamespacedName, podID int32) (uint64, *Status)
// ScoreExtensions returns a ScoreExtensions interface if it implements one, or nil if does not
ScoreExtensions() ScoreExtensions
}
// NoMaxResourceCountArgs holds arguments used to configure the NoMaxResourceCount plugin.
type NoMaxResourceCountArgs struct {
NumPartitions int
}
// EvenPodSpreadArgs holds arguments used to configure the EvenPodSpread plugin.
type EvenPodSpreadArgs struct {
MaxSkew int32
}
// AvailabilityZonePriorityArgs holds arguments used to configure the AvailabilityZonePriority plugin.
type AvailabilityZonePriorityArgs struct {
MaxSkew int32
}
// AvailabilityNodePriorityArgs holds arguments used to configure the AvailabilityNodePriority plugin.
type AvailabilityNodePriorityArgs struct {
MaxSkew int32
}
// Code is the Status code/type which is returned from plugins.
type Code int
// These are predefined codes used in a Status.
const (
// Success means that plugin ran correctly and found pod schedulable.
Success Code = iota
// Unschedulable is used when a plugin finds a pod unschedulable due to not satisying the predicate.
Unschedulable
// Error is used for internal plugin errors, unexpected input, etc.
Error
)
// Status indicates the result of running a plugin.
type Status struct {
code Code
reasons []string
err error
}
// Code returns code of the Status.
func (s *Status) Code() Code {
if s == nil {
return Success
}
return s.code
}
// Message returns a concatenated message on reasons of the Status.
func (s *Status) Message() string {
if s == nil {
return ""
}
return strings.Join(s.reasons, ", ")
}
// NewStatus makes a Status out of the given arguments and returns its pointer.
func NewStatus(code Code, reasons ...string) *Status {
s := &Status{
code: code,
reasons: reasons,
}
if code == Error {
s.err = errors.New(s.Message())
}
return s
}
// AsStatus wraps an error in a Status.
func AsStatus(err error) *Status {
return &Status{
code: Error,
reasons: []string{err.Error()},
err: err,
}
}
// AsError returns nil if the status is a success; otherwise returns an "error" object
// with a concatenated message on reasons of the Status.
func (s *Status) AsError() error {
if s.IsSuccess() {
return nil
}
if s.err != nil {
return s.err
}
return errors.New(s.Message())
}
// IsSuccess returns true if and only if "Status" is nil or Code is "Success".
func (s *Status) IsSuccess() bool {
return s.Code() == Success
}
// IsError returns true if and only if "Status" is "Error".
func (s *Status) IsError() bool {
return s.Code() == Error
}
// IsUnschedulable returns true if "Status" is Unschedulable
func (s *Status) IsUnschedulable() bool {
return s.Code() == Unschedulable
}
type PodScore struct {
ID int32
Score uint64
}
type PodScoreList []PodScore
// PluginToPodScores declares a map from plugin name to its PodScoreList.
type PluginToPodScores map[string]PodScoreList
// PluginToStatus maps plugin name to status. Currently used to identify which Filter plugin
// returned which status.
type PluginToStatus map[string]*Status
// Merge merges the statuses in the map into one. The resulting status code have the following
// precedence: Error, Unschedulable, Success
func (p PluginToStatus) Merge() *Status {
if len(p) == 0 {
return nil
}
finalStatus := NewStatus(Success)
for _, s := range p {
if s.Code() == Error {
finalStatus.err = s.AsError()
}
if s.Code() > finalStatus.code {
finalStatus.code = s.Code()
}
finalStatus.reasons = append(finalStatus.reasons, s.reasons...)
}
return finalStatus
}