2019-03-27 18:21:32 -04:00
/ *
Copyright 2019 The Kubernetes 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 .
* /
2020-06-19 05:05:45 -04:00
package runtime
2019-03-27 18:21:32 -04:00
import (
2019-07-16 09:19:20 -04:00
"context"
2019-03-27 18:21:32 -04:00
"fmt"
2019-09-26 21:15:32 -04:00
"reflect"
2020-11-10 19:41:18 -05:00
"sort"
2019-05-10 09:05:59 -04:00
"time"
2019-03-27 18:21:32 -04:00
2020-02-15 00:48:45 -05:00
v1 "k8s.io/api/core/v1"
2019-03-27 18:21:32 -04:00
"k8s.io/apimachinery/pkg/runtime"
2019-05-10 09:05:59 -04:00
"k8s.io/apimachinery/pkg/types"
2019-09-26 21:15:32 -04:00
"k8s.io/apimachinery/pkg/util/sets"
2019-10-09 02:49:56 -04:00
"k8s.io/client-go/informers"
2019-08-19 05:46:15 -04:00
clientset "k8s.io/client-go/kubernetes"
2021-03-29 15:27:27 -04:00
restclient "k8s.io/client-go/rest"
2020-06-10 18:51:32 -04:00
"k8s.io/client-go/tools/events"
2020-12-19 11:18:40 -05:00
"k8s.io/component-helpers/scheduling/corev1"
2020-04-17 15:25:06 -04:00
"k8s.io/klog/v2"
2019-05-04 06:29:30 -04:00
"k8s.io/kubernetes/pkg/scheduler/apis/config"
2020-10-09 10:41:44 -04:00
"k8s.io/kubernetes/pkg/scheduler/framework"
2021-10-20 13:35:12 -04:00
"k8s.io/kubernetes/pkg/scheduler/framework/parallelize"
2019-10-04 10:25:17 -04:00
"k8s.io/kubernetes/pkg/scheduler/metrics"
2019-03-27 18:21:32 -04:00
)
2019-10-04 17:40:21 -04:00
const (
// Specifies the maximum timeout a permit plugin can return.
2023-03-06 16:54:01 -05:00
maxTimeout = 15 * time . Minute
2019-10-04 17:40:21 -04:00
)
2020-06-19 05:05:45 -04:00
// frameworkImpl is the component responsible for initializing and running scheduler
2019-03-27 18:21:32 -04:00
// plugins.
2020-06-19 05:05:45 -04:00
type frameworkImpl struct {
2021-03-29 04:34:10 -04:00
registry Registry
snapshotSharedLister framework . SharedLister
waitingPods * waitingPodsMap
scorePluginWeight map [ string ] int
2022-11-07 17:02:22 -05:00
preEnqueuePlugins [ ] framework . PreEnqueuePlugin
2023-06-08 00:54:30 -04:00
enqueueExtensions [ ] framework . EnqueueExtensions
2021-03-29 04:34:10 -04:00
queueSortPlugins [ ] framework . QueueSortPlugin
preFilterPlugins [ ] framework . PreFilterPlugin
filterPlugins [ ] framework . FilterPlugin
postFilterPlugins [ ] framework . PostFilterPlugin
preScorePlugins [ ] framework . PreScorePlugin
scorePlugins [ ] framework . ScorePlugin
reservePlugins [ ] framework . ReservePlugin
preBindPlugins [ ] framework . PreBindPlugin
bindPlugins [ ] framework . BindPlugin
postBindPlugins [ ] framework . PostBindPlugin
permitPlugins [ ] framework . PermitPlugin
2019-08-19 05:46:15 -04:00
2019-10-09 02:49:56 -04:00
clientSet clientset . Interface
2021-03-29 15:27:27 -04:00
kubeConfig * restclient . Config
2020-06-10 18:51:32 -04:00
eventRecorder events . EventRecorder
2019-10-09 02:49:56 -04:00
informerFactory informers . SharedInformerFactory
2023-03-22 03:52:25 -04:00
logger klog . Logger
2019-10-29 10:54:02 -04:00
2023-02-04 07:03:01 -05:00
metricsRecorder * metrics . MetricAsyncRecorder
2022-09-16 16:18:12 -04:00
profileName string
percentageOfNodesToScore * int32
2019-12-20 16:50:17 -05:00
2021-02-26 11:44:05 -05:00
extenders [ ] framework . Extender
framework . PodNominator
2020-05-18 13:29:08 -04:00
2021-03-01 09:20:18 -05:00
parallelizer parallelize . Parallelizer
2019-03-27 18:21:32 -04:00
}
2019-10-04 17:40:21 -04:00
// extensionPoint encapsulates desired and applied set of plugins at a specific extension
// point. This is used to simplify iterating over all extension points supported by the
2020-06-19 05:05:45 -04:00
// frameworkImpl.
2019-10-04 17:40:21 -04:00
type extensionPoint struct {
// the set of plugins to be configured at this extension point.
2021-06-10 08:45:49 -04:00
plugins * config . PluginSet
2019-10-04 17:40:21 -04:00
// a pointer to the slice storing plugins implementations that will run at this
2019-12-12 02:44:37 -05:00
// extension point.
2019-10-04 17:40:21 -04:00
slicePtr interface { }
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) getExtensionPoints ( plugins * config . Plugins ) [ ] extensionPoint {
2019-10-04 17:40:21 -04:00
return [ ] extensionPoint {
2021-06-10 08:45:49 -04:00
{ & plugins . PreFilter , & f . preFilterPlugins } ,
{ & plugins . Filter , & f . filterPlugins } ,
{ & plugins . PostFilter , & f . postFilterPlugins } ,
{ & plugins . Reserve , & f . reservePlugins } ,
{ & plugins . PreScore , & f . preScorePlugins } ,
{ & plugins . Score , & f . scorePlugins } ,
{ & plugins . PreBind , & f . preBindPlugins } ,
{ & plugins . Bind , & f . bindPlugins } ,
{ & plugins . PostBind , & f . postBindPlugins } ,
{ & plugins . Permit , & f . permitPlugins } ,
2022-11-07 17:02:22 -05:00
{ & plugins . PreEnqueue , & f . preEnqueuePlugins } ,
2021-06-10 08:45:49 -04:00
{ & plugins . QueueSort , & f . queueSortPlugins } ,
2019-10-04 17:40:21 -04:00
}
}
2019-05-10 09:05:59 -04:00
2021-02-26 11:44:05 -05:00
// Extenders returns the registered extenders.
func ( f * frameworkImpl ) Extenders ( ) [ ] framework . Extender {
return f . extenders
}
2019-08-19 05:46:15 -04:00
type frameworkOptions struct {
2021-03-10 11:08:05 -05:00
componentConfigVersion string
clientSet clientset . Interface
kubeConfig * restclient . Config
eventRecorder events . EventRecorder
informerFactory informers . SharedInformerFactory
snapshotSharedLister framework . SharedLister
2023-02-04 07:03:01 -05:00
metricsRecorder * metrics . MetricAsyncRecorder
2021-03-10 11:08:05 -05:00
podNominator framework . PodNominator
extenders [ ] framework . Extender
captureProfile CaptureProfile
parallelizer parallelize . Parallelizer
2023-03-22 03:52:25 -04:00
logger * klog . Logger
2019-08-19 05:46:15 -04:00
}
2020-06-19 05:05:45 -04:00
// Option for the frameworkImpl.
2019-08-19 05:46:15 -04:00
type Option func ( * frameworkOptions )
2021-03-10 11:08:05 -05:00
// WithComponentConfigVersion sets the component config version to the
// KubeSchedulerConfiguration version used. The string should be the full
// scheme group/version of the external type we converted from (for example
2023-05-03 09:43:19 -04:00
// "kubescheduler.config.k8s.io/v1")
2021-03-10 11:08:05 -05:00
func WithComponentConfigVersion ( componentConfigVersion string ) Option {
return func ( o * frameworkOptions ) {
o . componentConfigVersion = componentConfigVersion
}
}
2020-06-19 05:05:45 -04:00
// WithClientSet sets clientSet for the scheduling frameworkImpl.
2019-08-19 05:46:15 -04:00
func WithClientSet ( clientSet clientset . Interface ) Option {
return func ( o * frameworkOptions ) {
o . clientSet = clientSet
}
}
2021-03-29 15:27:27 -04:00
// WithKubeConfig sets kubeConfig for the scheduling frameworkImpl.
func WithKubeConfig ( kubeConfig * restclient . Config ) Option {
return func ( o * frameworkOptions ) {
o . kubeConfig = kubeConfig
}
}
2020-06-19 05:05:45 -04:00
// WithEventRecorder sets clientSet for the scheduling frameworkImpl.
2020-06-10 18:51:32 -04:00
func WithEventRecorder ( recorder events . EventRecorder ) Option {
return func ( o * frameworkOptions ) {
o . eventRecorder = recorder
}
}
2020-06-19 05:05:45 -04:00
// WithInformerFactory sets informer factory for the scheduling frameworkImpl.
2019-10-09 02:49:56 -04:00
func WithInformerFactory ( informerFactory informers . SharedInformerFactory ) Option {
return func ( o * frameworkOptions ) {
o . informerFactory = informerFactory
}
}
2019-11-05 21:25:07 -05:00
// WithSnapshotSharedLister sets the SharedLister of the snapshot.
2020-06-19 05:05:45 -04:00
func WithSnapshotSharedLister ( snapshotSharedLister framework . SharedLister ) Option {
2019-10-24 18:30:21 -04:00
return func ( o * frameworkOptions ) {
2019-11-05 21:25:07 -05:00
o . snapshotSharedLister = snapshotSharedLister
2019-10-24 18:30:21 -04:00
}
}
2020-06-19 05:05:45 -04:00
// WithPodNominator sets podNominator for the scheduling frameworkImpl.
func WithPodNominator ( nominator framework . PodNominator ) Option {
2020-05-18 13:29:08 -04:00
return func ( o * frameworkOptions ) {
o . podNominator = nominator
}
}
2020-06-19 05:05:45 -04:00
// WithExtenders sets extenders for the scheduling frameworkImpl.
func WithExtenders ( extenders [ ] framework . Extender ) Option {
2020-04-23 20:08:59 -04:00
return func ( o * frameworkOptions ) {
o . extenders = extenders
}
}
2021-03-01 09:20:18 -05:00
// WithParallelism sets parallelism for the scheduling frameworkImpl.
func WithParallelism ( parallelism int ) Option {
return func ( o * frameworkOptions ) {
o . parallelizer = parallelize . NewParallelizer ( parallelism )
}
}
2020-11-10 19:41:18 -05:00
// CaptureProfile is a callback to capture a finalized profile.
type CaptureProfile func ( config . KubeSchedulerProfile )
// WithCaptureProfile sets a callback to capture the finalized profile.
func WithCaptureProfile ( c CaptureProfile ) Option {
return func ( o * frameworkOptions ) {
o . captureProfile = c
}
}
2023-03-01 21:57:50 -05:00
// WithMetricsRecorder sets metrics recorder for the scheduling frameworkImpl.
func WithMetricsRecorder ( r * metrics . MetricAsyncRecorder ) Option {
return func ( o * frameworkOptions ) {
o . metricsRecorder = r
}
}
2023-03-22 03:52:25 -04:00
// WithLogger overrides the default logger from k8s.io/klog.
func WithLogger ( logger klog . Logger ) Option {
return func ( o * frameworkOptions ) {
o . logger = & logger
}
}
2023-03-01 21:57:50 -05:00
// defaultFrameworkOptions are applied when no option corresponding to those fields exist.
2022-05-20 12:02:41 -04:00
func defaultFrameworkOptions ( stopCh <- chan struct { } ) frameworkOptions {
2021-01-22 01:40:06 -05:00
return frameworkOptions {
2023-02-04 07:03:01 -05:00
metricsRecorder : metrics . NewMetricsAsyncRecorder ( 1000 , time . Second , stopCh ) ,
2021-03-01 09:20:18 -05:00
parallelizer : parallelize . NewParallelizer ( parallelize . DefaultParallelism ) ,
2021-01-29 01:29:10 -05:00
}
}
2020-06-19 05:05:45 -04:00
var _ framework . Framework = & frameworkImpl { }
2019-03-27 18:21:32 -04:00
// NewFramework initializes plugins given the configuration and the registry.
2023-05-15 06:36:17 -04:00
func NewFramework ( ctx context . Context , r Registry , profile * config . KubeSchedulerProfile , opts ... Option ) ( framework . Framework , error ) {
options := defaultFrameworkOptions ( ctx . Done ( ) )
2019-08-19 05:46:15 -04:00
for _ , opt := range opts {
opt ( & options )
}
2023-05-15 06:36:17 -04:00
logger := klog . FromContext ( ctx )
2023-03-22 03:52:25 -04:00
if options . logger != nil {
logger = * options . logger
}
2020-06-19 05:05:45 -04:00
f := & frameworkImpl {
2021-03-29 04:34:10 -04:00
registry : r ,
snapshotSharedLister : options . snapshotSharedLister ,
scorePluginWeight : make ( map [ string ] int ) ,
waitingPods : newWaitingPodsMap ( ) ,
clientSet : options . clientSet ,
kubeConfig : options . kubeConfig ,
eventRecorder : options . eventRecorder ,
informerFactory : options . informerFactory ,
metricsRecorder : options . metricsRecorder ,
extenders : options . extenders ,
PodNominator : options . podNominator ,
parallelizer : options . parallelizer ,
2023-03-22 03:52:25 -04:00
logger : logger ,
2020-04-23 20:08:59 -04:00
}
2021-03-03 16:44:25 -05:00
if profile == nil {
return f , nil
}
f . profileName = profile . SchedulerName
2022-09-16 16:18:12 -04:00
f . percentageOfNodesToScore = profile . PercentageOfNodesToScore
2021-03-03 16:44:25 -05:00
if profile . Plugins == nil {
2019-05-04 06:29:30 -04:00
return f , nil
}
// get needed plugins from config
2021-03-03 16:44:25 -05:00
pg := f . pluginsNeeded ( profile . Plugins )
2019-03-27 18:21:32 -04:00
2021-03-03 16:44:25 -05:00
pluginConfig := make ( map [ string ] runtime . Object , len ( profile . PluginConfig ) )
for i := range profile . PluginConfig {
name := profile . PluginConfig [ i ] . Name
2020-03-05 13:52:40 -05:00
if _ , ok := pluginConfig [ name ] ; ok {
return nil , fmt . Errorf ( "repeated config for plugin %s" , name )
}
2021-03-03 16:44:25 -05:00
pluginConfig [ name ] = profile . PluginConfig [ i ] . Args
2019-10-04 17:40:21 -04:00
}
2020-11-10 19:41:18 -05:00
outputProfile := config . KubeSchedulerProfile {
2022-09-16 16:18:12 -04:00
SchedulerName : f . profileName ,
PercentageOfNodesToScore : f . percentageOfNodesToScore ,
Plugins : profile . Plugins ,
PluginConfig : make ( [ ] config . PluginConfig , 0 , len ( pg ) ) ,
2020-11-10 19:41:18 -05:00
}
2019-10-04 17:40:21 -04:00
2020-06-19 05:05:45 -04:00
pluginsMap := make ( map [ string ] framework . Plugin )
2019-03-27 18:21:32 -04:00
for name , factory := range r {
2019-10-04 17:40:21 -04:00
// initialize only needed plugins.
2022-03-30 08:47:46 -04:00
if ! pg . Has ( name ) {
2019-05-04 06:29:30 -04:00
continue
}
2021-06-10 08:45:49 -04:00
args := pluginConfig [ name ]
2020-11-10 19:41:18 -05:00
if args != nil {
outputProfile . PluginConfig = append ( outputProfile . PluginConfig , config . PluginConfig {
Name : name ,
Args : args ,
} )
}
2023-09-05 23:55:33 -04:00
p , err := factory ( ctx , args , f )
2019-03-27 18:21:32 -04:00
if err != nil {
2020-09-24 09:10:42 -04:00
return nil , fmt . Errorf ( "initializing plugin %q: %w" , name , err )
2019-03-27 18:21:32 -04:00
}
2019-07-16 09:19:20 -04:00
pluginsMap [ name ] = p
2023-06-08 00:54:30 -04:00
f . fillEnqueueExtensions ( p )
2019-05-04 06:29:30 -04:00
}
2019-03-27 18:21:32 -04:00
2021-10-11 13:47:23 -04:00
// initialize plugins per individual extension points
2021-03-03 16:44:25 -05:00
for _ , e := range f . getExtensionPoints ( profile . Plugins ) {
2021-06-10 08:45:49 -04:00
if err := updatePluginList ( e . slicePtr , * e . plugins , pluginsMap ) ; err != nil {
2019-10-04 17:40:21 -04:00
return nil , err
}
2019-09-26 21:15:32 -04:00
}
2021-10-11 13:47:23 -04:00
// initialize multiPoint plugins to their expanded extension points
if len ( profile . Plugins . MultiPoint . Enabled ) > 0 {
2023-03-22 03:52:25 -04:00
if err := f . expandMultiPointPlugins ( logger , profile , pluginsMap ) ; err != nil {
2021-10-11 13:47:23 -04:00
return nil , err
}
}
if len ( f . queueSortPlugins ) != 1 {
2022-05-23 04:34:50 -04:00
return nil , fmt . Errorf ( "only one queue sort plugin required for profile with scheduler name %q, but got %d" , profile . SchedulerName , len ( f . queueSortPlugins ) )
}
if len ( f . bindPlugins ) == 0 {
return nil , fmt . Errorf ( "at least one bind plugin is needed for profile with scheduler name %q" , profile . SchedulerName )
2021-10-11 13:47:23 -04:00
}
if err := getScoreWeights ( f , pluginsMap , append ( profile . Plugins . Score . Enabled , profile . Plugins . MultiPoint . Enabled ... ) ) ; err != nil {
return nil , err
}
2019-10-04 17:40:21 -04:00
// Verifying the score weights again since Plugin.Name() could return a different
// value from the one used in the configuration.
2019-09-26 21:15:32 -04:00
for _ , scorePlugin := range f . scorePlugins {
2021-03-29 04:34:10 -04:00
if f . scorePluginWeight [ scorePlugin . Name ( ) ] == 0 {
2019-09-26 21:15:32 -04:00
return nil , fmt . Errorf ( "score plugin %q is not configured with weight" , scorePlugin . Name ( ) )
2019-05-10 09:05:59 -04:00
}
2019-03-27 18:21:32 -04:00
}
2019-05-04 06:29:30 -04:00
2020-11-10 19:41:18 -05:00
if options . captureProfile != nil {
if len ( outputProfile . PluginConfig ) != 0 {
sort . Slice ( outputProfile . PluginConfig , func ( i , j int ) bool {
return outputProfile . PluginConfig [ i ] . Name < outputProfile . PluginConfig [ j ] . Name
} )
} else {
outputProfile . PluginConfig = nil
}
options . captureProfile ( outputProfile )
}
2023-05-16 00:00:17 -04:00
f . setInstrumentedPlugins ( )
return f , nil
}
// setInstrumentedPlugins initializes instrumented plugins from current plugins that frameworkImpl has.
func ( f * frameworkImpl ) setInstrumentedPlugins ( ) {
2023-04-25 10:18:05 -04:00
// Cache metric streams for prefilter and filter plugins.
for i , pl := range f . preFilterPlugins {
f . preFilterPlugins [ i ] = & instrumentedPreFilterPlugin {
PreFilterPlugin : f . preFilterPlugins [ i ] ,
metric : metrics . PluginEvaluationTotal . WithLabelValues ( pl . Name ( ) , metrics . PreFilter , f . profileName ) ,
}
}
for i , pl := range f . filterPlugins {
f . filterPlugins [ i ] = & instrumentedFilterPlugin {
FilterPlugin : f . filterPlugins [ i ] ,
metric : metrics . PluginEvaluationTotal . WithLabelValues ( pl . Name ( ) , metrics . Filter , f . profileName ) ,
}
}
2023-05-16 00:00:17 -04:00
// Cache metric streams for prescore and score plugins.
for i , pl := range f . preScorePlugins {
f . preScorePlugins [ i ] = & instrumentedPreScorePlugin {
PreScorePlugin : f . preScorePlugins [ i ] ,
metric : metrics . PluginEvaluationTotal . WithLabelValues ( pl . Name ( ) , metrics . PreScore , f . profileName ) ,
}
}
for i , pl := range f . scorePlugins {
f . scorePlugins [ i ] = & instrumentedScorePlugin {
ScorePlugin : f . scorePlugins [ i ] ,
metric : metrics . PluginEvaluationTotal . WithLabelValues ( pl . Name ( ) , metrics . Score , f . profileName ) ,
}
}
2019-03-27 18:21:32 -04:00
}
2023-03-08 16:18:36 -05:00
func ( f * frameworkImpl ) SetPodNominator ( n framework . PodNominator ) {
f . PodNominator = n
}
2021-10-11 13:47:23 -04:00
// getScoreWeights makes sure that, between MultiPoint-Score plugin weights and individual Score
// plugin weights there is not an overflow of MaxTotalScore.
func getScoreWeights ( f * frameworkImpl , pluginsMap map [ string ] framework . Plugin , plugins [ ] config . Plugin ) error {
var totalPriority int64
scorePlugins := reflect . ValueOf ( & f . scorePlugins ) . Elem ( )
pluginType := scorePlugins . Type ( ) . Elem ( )
for _ , e := range plugins {
pg := pluginsMap [ e . Name ]
if ! reflect . TypeOf ( pg ) . Implements ( pluginType ) {
continue
}
// We append MultiPoint plugins to the list of Score plugins. So if this plugin has already been
// encountered, let the individual Score weight take precedence.
if _ , ok := f . scorePluginWeight [ e . Name ] ; ok {
continue
}
// a weight of zero is not permitted, plugins can be disabled explicitly
// when configured.
f . scorePluginWeight [ e . Name ] = int ( e . Weight )
if f . scorePluginWeight [ e . Name ] == 0 {
f . scorePluginWeight [ e . Name ] = 1
}
// Checks totalPriority against MaxTotalScore to avoid overflow
if int64 ( f . scorePluginWeight [ e . Name ] ) * framework . MaxNodeScore > framework . MaxTotalScore - totalPriority {
return fmt . Errorf ( "total score of Score plugins could overflow" )
}
totalPriority += int64 ( f . scorePluginWeight [ e . Name ] ) * framework . MaxNodeScore
}
return nil
}
2022-03-21 12:30:41 -04:00
type orderedSet struct {
set map [ string ] int
list [ ] string
deletionCnt int
}
func newOrderedSet ( ) * orderedSet {
return & orderedSet { set : make ( map [ string ] int ) }
}
func ( os * orderedSet ) insert ( s string ) {
if os . has ( s ) {
return
}
os . set [ s ] = len ( os . list )
os . list = append ( os . list , s )
}
func ( os * orderedSet ) has ( s string ) bool {
_ , found := os . set [ s ]
return found
}
func ( os * orderedSet ) delete ( s string ) {
if i , found := os . set [ s ] ; found {
delete ( os . set , s )
os . list = append ( os . list [ : i - os . deletionCnt ] , os . list [ i + 1 - os . deletionCnt : ] ... )
os . deletionCnt ++
}
}
2023-03-22 03:52:25 -04:00
func ( f * frameworkImpl ) expandMultiPointPlugins ( logger klog . Logger , profile * config . KubeSchedulerProfile , pluginsMap map [ string ] framework . Plugin ) error {
2021-10-11 13:47:23 -04:00
// initialize MultiPoint plugins
for _ , e := range f . getExtensionPoints ( profile . Plugins ) {
plugins := reflect . ValueOf ( e . slicePtr ) . Elem ( )
pluginType := plugins . Type ( ) . Elem ( )
// build enabledSet of plugins already registered via normal extension points
// to check double registration
2022-03-21 12:30:41 -04:00
enabledSet := newOrderedSet ( )
2021-10-11 13:47:23 -04:00
for _ , plugin := range e . plugins . Enabled {
2022-03-21 12:30:41 -04:00
enabledSet . insert ( plugin . Name )
2021-10-11 13:47:23 -04:00
}
2023-03-27 03:46:13 -04:00
disabledSet := sets . New [ string ] ( )
2021-10-11 13:47:23 -04:00
for _ , disabledPlugin := range e . plugins . Disabled {
disabledSet . Insert ( disabledPlugin . Name )
}
if disabledSet . Has ( "*" ) {
2023-03-22 03:52:25 -04:00
logger . V ( 4 ) . Info ( "Skipped MultiPoint expansion because all plugins are disabled for extension point" , "extension" , pluginType )
2021-10-11 13:47:23 -04:00
continue
}
// track plugins enabled via multipoint separately from those enabled by specific extensions,
// so that we can distinguish between double-registration and explicit overrides
2022-03-21 12:30:41 -04:00
multiPointEnabled := newOrderedSet ( )
overridePlugins := newOrderedSet ( )
2021-10-11 13:47:23 -04:00
for _ , ep := range profile . Plugins . MultiPoint . Enabled {
pg , ok := pluginsMap [ ep . Name ]
if ! ok {
return fmt . Errorf ( "%s %q does not exist" , pluginType . Name ( ) , ep . Name )
}
// if this plugin doesn't implement the type for the current extension we're trying to expand, skip
if ! reflect . TypeOf ( pg ) . Implements ( pluginType ) {
continue
}
// a plugin that's enabled via MultiPoint can still be disabled for specific extension points
if disabledSet . Has ( ep . Name ) {
2023-03-22 03:52:25 -04:00
logger . V ( 4 ) . Info ( "Skipped disabled plugin for extension point" , "plugin" , ep . Name , "extension" , pluginType )
2021-10-11 13:47:23 -04:00
continue
}
// if this plugin has already been enabled by the specific extension point,
// the user intent is to override the default plugin or make some other explicit setting.
// Either way, discard the MultiPoint value for this plugin.
// This maintains expected behavior for overriding default plugins (see https://github.com/kubernetes/kubernetes/pull/99582)
2022-03-21 12:30:41 -04:00
if enabledSet . has ( ep . Name ) {
overridePlugins . insert ( ep . Name )
2023-03-22 03:52:25 -04:00
logger . Info ( "MultiPoint plugin is explicitly re-configured; overriding" , "plugin" , ep . Name )
2021-10-11 13:47:23 -04:00
continue
}
// if this plugin is already registered via MultiPoint, then this is
// a double registration and an error in the config.
2022-03-21 12:30:41 -04:00
if multiPointEnabled . has ( ep . Name ) {
2021-10-11 13:47:23 -04:00
return fmt . Errorf ( "plugin %q already registered as %q" , ep . Name , pluginType . Name ( ) )
}
// we only need to update the multipoint set, since we already have the specific extension set from above
2022-03-21 12:30:41 -04:00
multiPointEnabled . insert ( ep . Name )
}
2021-10-11 13:47:23 -04:00
2022-03-21 12:30:41 -04:00
// Reorder plugins. Here is the expected order:
// - part 1: overridePlugins. Their order stay intact as how they're specified in regular extension point.
// - part 2: multiPointEnabled - i.e., plugin defined in multipoint but not in regular extension point.
// - part 3: other plugins (excluded by part 1 & 2) in regular extension point.
newPlugins := reflect . New ( reflect . TypeOf ( e . slicePtr ) . Elem ( ) ) . Elem ( )
// part 1
for _ , name := range enabledSet . list {
if overridePlugins . has ( name ) {
newPlugins = reflect . Append ( newPlugins , reflect . ValueOf ( pluginsMap [ name ] ) )
enabledSet . delete ( name )
}
}
// part 2
for _ , name := range multiPointEnabled . list {
newPlugins = reflect . Append ( newPlugins , reflect . ValueOf ( pluginsMap [ name ] ) )
}
// part 3
for _ , name := range enabledSet . list {
newPlugins = reflect . Append ( newPlugins , reflect . ValueOf ( pluginsMap [ name ] ) )
2021-10-11 13:47:23 -04:00
}
2022-03-21 12:30:41 -04:00
plugins . Set ( newPlugins )
2021-10-11 13:47:23 -04:00
}
return nil
}
2023-10-27 10:03:44 -04:00
func shouldHaveEnqueueExtensions ( p framework . Plugin ) bool {
switch p . ( type ) {
// Only PreEnqueue, PreFilter, Filter, Reserve, and Permit plugins can (should) have EnqueueExtensions.
// See the comment of EnqueueExtensions for more detailed reason here.
case framework . PreEnqueuePlugin , framework . PreFilterPlugin , framework . FilterPlugin , framework . ReservePlugin , framework . PermitPlugin :
return true
}
return false
}
2023-06-08 00:54:30 -04:00
func ( f * frameworkImpl ) fillEnqueueExtensions ( p framework . Plugin ) {
2023-10-27 10:03:44 -04:00
if ! shouldHaveEnqueueExtensions ( p ) {
// Ignore EnqueueExtensions from plugin which isn't PreEnqueue, PreFilter, Filter, Reserve, and Permit.
return
}
2021-01-29 01:29:10 -05:00
ext , ok := p . ( framework . EnqueueExtensions )
if ! ok {
2023-06-08 00:54:30 -04:00
// If interface EnqueueExtensions is not implemented, register the default enqueue extensions
// to the plugin because we don't know which events the plugin is interested in.
// This is to ensure backward compatibility.
f . enqueueExtensions = append ( f . enqueueExtensions , & defaultEnqueueExtension { pluginName : p . Name ( ) } )
2021-01-29 01:29:10 -05:00
return
}
2023-06-08 00:54:30 -04:00
f . enqueueExtensions = append ( f . enqueueExtensions , ext )
2021-01-29 01:29:10 -05:00
}
2023-06-08 00:54:30 -04:00
// defaultEnqueueExtension is used when a plugin does not implement EnqueueExtensions interface.
type defaultEnqueueExtension struct {
pluginName string
}
func ( p * defaultEnqueueExtension ) Name ( ) string { return p . pluginName }
func ( p * defaultEnqueueExtension ) EventsToRegister ( ) [ ] framework . ClusterEventWithHint {
// need to return all specific cluster events with framework.All action instead of wildcard event
// because the returning values are used to register event handlers.
// If we return the wildcard here, it won't affect the event handlers registered by the plugin
// and some events may not be registered in the event handlers.
2023-07-04 11:00:12 -04:00
return framework . UnrollWildCardResource ( )
2021-01-29 01:29:10 -05:00
}
2021-02-10 10:45:59 -05:00
func updatePluginList ( pluginList interface { } , pluginSet config . PluginSet , pluginsMap map [ string ] framework . Plugin ) error {
2019-10-04 12:40:21 -04:00
plugins := reflect . ValueOf ( pluginList ) . Elem ( )
pluginType := plugins . Type ( ) . Elem ( )
2023-03-27 03:46:13 -04:00
set := sets . New [ string ] ( )
2019-09-26 21:15:32 -04:00
for _ , ep := range pluginSet . Enabled {
pg , ok := pluginsMap [ ep . Name ]
if ! ok {
2019-10-04 17:40:21 -04:00
return fmt . Errorf ( "%s %q does not exist" , pluginType . Name ( ) , ep . Name )
2019-09-26 21:15:32 -04:00
}
if ! reflect . TypeOf ( pg ) . Implements ( pluginType ) {
2019-10-04 17:40:21 -04:00
return fmt . Errorf ( "plugin %q does not extend %s plugin" , ep . Name , pluginType . Name ( ) )
2019-09-26 21:15:32 -04:00
}
if set . Has ( ep . Name ) {
2019-10-04 17:40:21 -04:00
return fmt . Errorf ( "plugin %q already registered as %q" , ep . Name , pluginType . Name ( ) )
2019-09-26 21:15:32 -04:00
}
set . Insert ( ep . Name )
newPlugins := reflect . Append ( plugins , reflect . ValueOf ( pg ) )
plugins . Set ( newPlugins )
}
return nil
}
2023-06-05 05:29:49 -04:00
// PreEnqueuePlugins returns the registered preEnqueue plugins.
2022-11-07 17:02:22 -05:00
func ( f * frameworkImpl ) PreEnqueuePlugins ( ) [ ] framework . PreEnqueuePlugin {
return f . preEnqueuePlugins
}
2023-06-08 00:54:30 -04:00
// EnqueueExtensions returns the registered reenqueue plugins.
func ( f * frameworkImpl ) EnqueueExtensions ( ) [ ] framework . EnqueueExtensions {
return f . enqueueExtensions
}
2019-05-06 21:03:00 -04:00
// QueueSortFunc returns the function to sort pods in scheduling queue
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) QueueSortFunc ( ) framework . LessFunc {
2020-01-15 15:26:22 -05:00
if f == nil {
2020-06-19 05:05:45 -04:00
// If frameworkImpl is nil, simply keep their order unchanged.
2020-01-15 15:26:22 -05:00
// NOTE: this is primarily for tests.
2020-06-19 05:05:45 -04:00
return func ( _ , _ * framework . QueuedPodInfo ) bool { return false }
2020-01-15 15:26:22 -05:00
}
2019-05-06 21:03:00 -04:00
if len ( f . queueSortPlugins ) == 0 {
2020-06-19 05:05:45 -04:00
panic ( "No QueueSort plugin is registered in the frameworkImpl." )
2019-05-06 21:03:00 -04:00
}
// Only one QueueSort plugin can be enabled.
return f . queueSortPlugins [ 0 ] . Less
}
2019-08-22 13:56:28 -04:00
// RunPreFilterPlugins runs the set of configured PreFilter plugins. It returns
2019-06-10 17:01:50 -04:00
// *Status and its code is set to non-success if any of the plugins returns
2023-01-05 12:48:46 -05:00
// anything but Success/Skip.
// When it returns Skip status, returned PreFilterResult and other fields in status are just ignored,
// and coupled Filter plugin/PreFilterExtensions() will be skipped in this scheduling cycle.
// If a non-success status is returned, then the scheduling cycle is aborted.
2022-03-10 17:48:33 -05:00
func ( f * frameworkImpl ) RunPreFilterPlugins ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod ) ( _ * framework . PreFilterResult , status * framework . Status ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
2023-08-05 20:39:01 -04:00
skipPlugins := sets . New [ string ] ( )
2020-01-08 23:23:05 -05:00
defer func ( ) {
2023-08-05 20:39:01 -04:00
state . SkipFilterPlugins = skipPlugins
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . PreFilter , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2022-03-10 17:48:33 -05:00
var result * framework . PreFilterResult
var pluginsWithNodes [ ] string
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "PreFilter" )
}
2019-08-22 13:56:28 -04:00
for _ , pl := range f . preFilterPlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2022-03-10 17:48:33 -05:00
r , s := f . runPreFilterPlugin ( ctx , pl , state , pod )
2023-01-05 12:48:46 -05:00
if s . IsSkip ( ) {
skipPlugins . Insert ( pl . Name ( ) )
continue
}
2022-11-09 06:55:33 -05:00
if ! s . IsSuccess ( ) {
2023-10-25 08:01:07 -04:00
s . SetPlugin ( pl . Name ( ) )
if s . IsRejected ( ) {
2022-03-10 17:48:33 -05:00
return nil , s
2019-06-10 17:01:50 -04:00
}
2023-10-25 08:01:07 -04:00
return nil , framework . AsStatus ( fmt . Errorf ( "running PreFilter plugin %q: %w" , pl . Name ( ) , s . AsError ( ) ) ) . WithPlugin ( pl . Name ( ) )
2022-03-10 17:48:33 -05:00
}
if ! r . AllNodes ( ) {
pluginsWithNodes = append ( pluginsWithNodes , pl . Name ( ) )
}
result = result . Merge ( r )
if ! result . AllNodes ( ) && len ( result . NodeNames ) == 0 {
msg := fmt . Sprintf ( "node(s) didn't satisfy plugin(s) %v simultaneously" , pluginsWithNodes )
if len ( pluginsWithNodes ) == 1 {
msg = fmt . Sprintf ( "node(s) didn't satisfy plugin %v" , pluginsWithNodes [ 0 ] )
}
return nil , framework . NewStatus ( framework . Unschedulable , msg )
2019-06-10 17:01:50 -04:00
}
2022-03-10 17:48:33 -05:00
}
return result , nil
2019-06-10 17:01:50 -04:00
}
2022-03-10 17:48:33 -05:00
func ( f * frameworkImpl ) runPreFilterPlugin ( ctx context . Context , pl framework . PreFilterPlugin , state * framework . CycleState , pod * v1 . Pod ) ( * framework . PreFilterResult , * framework . Status ) {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return pl . PreFilter ( ctx , state , pod )
}
startTime := time . Now ( )
2022-03-10 17:48:33 -05:00
result , status := pl . PreFilter ( ctx , state , pod )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . PreFilter , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2022-03-10 17:48:33 -05:00
return result , status
2019-10-29 10:54:02 -04:00
}
2019-10-01 11:59:48 -04:00
// RunPreFilterExtensionAddPod calls the AddPod interface for the set of configured
2019-09-24 12:39:27 -04:00
// PreFilter plugins. It returns directly if any of the plugins return any
// status other than Success.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunPreFilterExtensionAddPod (
2019-08-28 07:12:02 -04:00
ctx context . Context ,
2020-06-19 05:05:45 -04:00
state * framework . CycleState ,
2019-08-28 07:12:02 -04:00
podToSchedule * v1 . Pod ,
2020-12-30 03:42:06 -05:00
podInfoToAdd * framework . PodInfo ,
2020-06-19 05:05:45 -04:00
nodeInfo * framework . NodeInfo ,
) ( status * framework . Status ) {
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "PreFilterExtension" )
}
2019-09-24 12:39:27 -04:00
for _ , pl := range f . preFilterPlugins {
2023-01-05 12:48:46 -05:00
if pl . PreFilterExtensions ( ) == nil || state . SkipFilterPlugins . Has ( pl . Name ( ) ) {
2019-10-01 11:59:48 -04:00
continue
}
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2020-12-30 03:42:06 -05:00
status = f . runPreFilterExtensionAddPod ( ctx , pl , state , podToSchedule , podInfoToAdd , nodeInfo )
2019-10-29 10:54:02 -04:00
if ! status . IsSuccess ( ) {
2020-09-24 09:10:42 -04:00
err := status . AsError ( )
2023-03-22 03:52:25 -04:00
logger . Error ( err , "Plugin failed" , "pod" , klog . KObj ( podToSchedule ) , "node" , klog . KObj ( nodeInfo . Node ( ) ) , "operation" , "addPod" , "plugin" , pl . Name ( ) )
2020-09-24 09:10:42 -04:00
return framework . AsStatus ( fmt . Errorf ( "running AddPod on PreFilter plugin %q: %w" , pl . Name ( ) , err ) )
2019-09-24 12:39:27 -04:00
}
}
return nil
}
2020-12-30 03:42:06 -05:00
func ( f * frameworkImpl ) runPreFilterExtensionAddPod ( ctx context . Context , pl framework . PreFilterPlugin , state * framework . CycleState , podToSchedule * v1 . Pod , podInfoToAdd * framework . PodInfo , nodeInfo * framework . NodeInfo ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2020-12-30 03:42:06 -05:00
return pl . PreFilterExtensions ( ) . AddPod ( ctx , state , podToSchedule , podInfoToAdd , nodeInfo )
2019-10-29 10:54:02 -04:00
}
startTime := time . Now ( )
2020-12-30 03:42:06 -05:00
status := pl . PreFilterExtensions ( ) . AddPod ( ctx , state , podToSchedule , podInfoToAdd , nodeInfo )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . PreFilterExtensionAddPod , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
2019-10-01 11:59:48 -04:00
// RunPreFilterExtensionRemovePod calls the RemovePod interface for the set of configured
2019-09-24 12:39:27 -04:00
// PreFilter plugins. It returns directly if any of the plugins return any
// status other than Success.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunPreFilterExtensionRemovePod (
2019-08-28 07:12:02 -04:00
ctx context . Context ,
2020-06-19 05:05:45 -04:00
state * framework . CycleState ,
2019-08-28 07:12:02 -04:00
podToSchedule * v1 . Pod ,
2020-12-30 03:42:06 -05:00
podInfoToRemove * framework . PodInfo ,
2020-06-19 05:05:45 -04:00
nodeInfo * framework . NodeInfo ,
) ( status * framework . Status ) {
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "PreFilterExtension" )
}
2019-09-24 12:39:27 -04:00
for _ , pl := range f . preFilterPlugins {
2023-01-05 12:48:46 -05:00
if pl . PreFilterExtensions ( ) == nil || state . SkipFilterPlugins . Has ( pl . Name ( ) ) {
2019-10-01 11:59:48 -04:00
continue
}
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2020-12-30 03:42:06 -05:00
status = f . runPreFilterExtensionRemovePod ( ctx , pl , state , podToSchedule , podInfoToRemove , nodeInfo )
2019-10-29 10:54:02 -04:00
if ! status . IsSuccess ( ) {
2020-09-24 09:10:42 -04:00
err := status . AsError ( )
2023-03-22 03:52:25 -04:00
logger . Error ( err , "Plugin failed" , "node" , klog . KObj ( nodeInfo . Node ( ) ) , "operation" , "removePod" , "plugin" , pl . Name ( ) , "pod" , klog . KObj ( podToSchedule ) )
2020-09-24 09:10:42 -04:00
return framework . AsStatus ( fmt . Errorf ( "running RemovePod on PreFilter plugin %q: %w" , pl . Name ( ) , err ) )
2019-09-24 12:39:27 -04:00
}
}
return nil
}
2020-12-30 03:42:06 -05:00
func ( f * frameworkImpl ) runPreFilterExtensionRemovePod ( ctx context . Context , pl framework . PreFilterPlugin , state * framework . CycleState , podToSchedule * v1 . Pod , podInfoToRemove * framework . PodInfo , nodeInfo * framework . NodeInfo ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2020-12-30 03:42:06 -05:00
return pl . PreFilterExtensions ( ) . RemovePod ( ctx , state , podToSchedule , podInfoToRemove , nodeInfo )
2019-10-29 10:54:02 -04:00
}
startTime := time . Now ( )
2020-12-30 03:42:06 -05:00
status := pl . PreFilterExtensions ( ) . RemovePod ( ctx , state , podToSchedule , podInfoToRemove , nodeInfo )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . PreFilterExtensionRemovePod , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
2019-05-29 05:02:53 -04:00
// RunFilterPlugins runs the set of configured Filter plugins for pod on
// the given node. If any of these plugins doesn't return "Success", the
// given node is not suitable for running pod.
// Meanwhile, the failure message and status are set for the given node.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunFilterPlugins (
2019-08-28 07:12:02 -04:00
ctx context . Context ,
2020-06-19 05:05:45 -04:00
state * framework . CycleState ,
2019-08-28 07:12:02 -04:00
pod * v1 . Pod ,
2020-06-19 05:05:45 -04:00
nodeInfo * framework . NodeInfo ,
2023-01-03 01:33:58 -05:00
) * framework . Status {
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "Filter" )
}
2023-03-22 03:52:25 -04:00
2019-07-31 03:27:03 -04:00
for _ , pl := range f . filterPlugins {
2023-01-05 12:48:46 -05:00
if state . SkipFilterPlugins . Has ( pl . Name ( ) ) {
continue
}
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2023-01-03 21:49:57 -05:00
if status := f . runFilterPlugin ( ctx , pl , state , pod , nodeInfo ) ; ! status . IsSuccess ( ) {
2023-10-25 08:01:07 -04:00
if ! status . IsRejected ( ) {
2019-12-20 16:50:17 -05:00
// Filter plugins are not supposed to return any status other than
// Success or Unschedulable.
2023-01-03 01:33:58 -05:00
status = framework . AsStatus ( fmt . Errorf ( "running %q filter plugin: %w" , pl . Name ( ) , status . AsError ( ) ) )
2019-12-20 16:50:17 -05:00
}
2023-10-25 08:01:07 -04:00
status . SetPlugin ( pl . Name ( ) )
2023-01-03 01:33:58 -05:00
return status
2019-05-29 05:02:53 -04:00
}
}
2023-01-03 21:49:57 -05:00
return nil
2019-05-29 05:02:53 -04:00
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runFilterPlugin ( ctx context . Context , pl framework . FilterPlugin , state * framework . CycleState , pod * v1 . Pod , nodeInfo * framework . NodeInfo ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return pl . Filter ( ctx , state , pod , nodeInfo )
}
startTime := time . Now ( )
status := pl . Filter ( ctx , state , pod , nodeInfo )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . Filter , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
2020-06-05 16:02:45 -04:00
// RunPostFilterPlugins runs the set of configured PostFilter plugins until the first
2023-01-05 03:59:19 -05:00
// Success, Error or UnschedulableAndUnresolvable is met; otherwise continues to execute all plugins.
2020-06-22 20:22:27 -04:00
func ( f * frameworkImpl ) RunPostFilterPlugins ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , filteredNodeStatusMap framework . NodeToStatusMap ) ( _ * framework . PostFilterResult , status * framework . Status ) {
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . PostFilter , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-06-22 20:22:27 -04:00
} ( )
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "PostFilter" )
}
2023-03-22 03:52:25 -04:00
2021-12-16 13:54:58 -05:00
// `result` records the last meaningful(non-noop) PostFilterResult.
var result * framework . PostFilterResult
2023-01-05 03:59:19 -05:00
var reasons [ ] string
2023-10-25 08:01:07 -04:00
var rejectorPlugin string
2020-06-05 16:02:45 -04:00
for _ , pl := range f . postFilterPlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2020-06-05 16:02:45 -04:00
r , s := f . runPostFilterPlugin ( ctx , pl , state , pod , filteredNodeStatusMap )
if s . IsSuccess ( ) {
return r , s
2023-01-05 03:59:19 -05:00
} else if s . Code ( ) == framework . UnschedulableAndUnresolvable {
2023-10-25 08:01:07 -04:00
return r , s . WithPlugin ( pl . Name ( ) )
} else if ! s . IsRejected ( ) {
2023-01-05 03:59:19 -05:00
// Any status other than Success, Unschedulable or UnschedulableAndUnresolvable is Error.
2023-10-25 08:01:07 -04:00
return nil , framework . AsStatus ( s . AsError ( ) ) . WithPlugin ( pl . Name ( ) )
2021-12-16 13:54:58 -05:00
} else if r != nil && r . Mode ( ) != framework . ModeNoop {
result = r
2020-06-05 16:02:45 -04:00
}
2023-01-05 03:59:19 -05:00
reasons = append ( reasons , s . Reasons ( ) ... )
// Record the first failed plugin unless we proved that
// the latter is more relevant.
2023-10-25 08:01:07 -04:00
if len ( rejectorPlugin ) == 0 {
rejectorPlugin = pl . Name ( )
2023-01-05 03:59:19 -05:00
}
2020-06-05 16:02:45 -04:00
}
2020-06-22 20:22:27 -04:00
2023-10-25 08:01:07 -04:00
return result , framework . NewStatus ( framework . Unschedulable , reasons ... ) . WithPlugin ( rejectorPlugin )
2020-06-05 16:02:45 -04:00
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runPostFilterPlugin ( ctx context . Context , pl framework . PostFilterPlugin , state * framework . CycleState , pod * v1 . Pod , filteredNodeStatusMap framework . NodeToStatusMap ) ( * framework . PostFilterResult , * framework . Status ) {
2020-06-05 16:02:45 -04:00
if ! state . ShouldRecordPluginMetrics ( ) {
return pl . PostFilter ( ctx , state , pod , filteredNodeStatusMap )
}
startTime := time . Now ( )
r , s := pl . PostFilter ( ctx , state , pod , filteredNodeStatusMap )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . PostFilter , pl . Name ( ) , s . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2020-06-05 16:02:45 -04:00
return r , s
}
2020-12-19 11:18:40 -05:00
// RunFilterPluginsWithNominatedPods runs the set of configured filter plugins
// for nominated pod on the given node.
// This function is called from two different places: Schedule and Preempt.
// When it is called from Schedule, we want to test whether the pod is
// schedulable on the node with all the existing pods on the node plus higher
// and equal priority pods nominated to run on the node.
// When it is called from Preempt, we should remove the victims of preemption
// and add the nominated pods. Removal of the victims is done by
// SelectVictimsOnNode(). Preempt removes victims from PreFilter state and
// NodeInfo before calling this function.
func ( f * frameworkImpl ) RunFilterPluginsWithNominatedPods ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , info * framework . NodeInfo ) * framework . Status {
var status * framework . Status
podsAdded := false
// We run filters twice in some cases. If the node has greater or equal priority
// nominated pods, we run them when those pods are added to PreFilter state and nodeInfo.
// If all filters succeed in this pass, we run them again when these
// nominated pods are not added. This second pass is necessary because some
// filters such as inter-pod affinity may not pass without the nominated pods.
// If there are no nominated pods for the node or if the first run of the
// filters fail, we don't run the second pass.
// We consider only equal or higher priority pods in the first pass, because
// those are the current "pod" must yield to them and not take a space opened
// for running them. It is ok if the current "pod" take resources freed for
// lower priority pods.
// Requiring that the new pod is schedulable in both circumstances ensures that
// we are making a conservative decision: filters like resources and inter-pod
// anti-affinity are more likely to fail when the nominated pods are treated
// as running, while filters like pod affinity are more likely to fail when
// the nominated pods are treated as not running. We can't just assume the
// nominated pods are running because they are not running right now and in fact,
// they may end up getting scheduled to a different node.
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
logger = klog . LoggerWithName ( logger , "FilterWithNominatedPods" )
ctx = klog . NewContext ( ctx , logger )
2020-12-19 11:18:40 -05:00
for i := 0 ; i < 2 ; i ++ {
stateToUse := state
nodeInfoToUse := info
if i == 0 {
var err error
2021-02-26 11:44:05 -05:00
podsAdded , stateToUse , nodeInfoToUse , err = addNominatedPods ( ctx , f , pod , state , info )
2020-12-19 11:18:40 -05:00
if err != nil {
2021-01-26 00:48:58 -05:00
return framework . AsStatus ( err )
2020-12-19 11:18:40 -05:00
}
} else if ! podsAdded || ! status . IsSuccess ( ) {
break
}
2023-01-03 01:33:58 -05:00
status = f . RunFilterPlugins ( ctx , stateToUse , pod , nodeInfoToUse )
2023-10-25 08:01:07 -04:00
if ! status . IsSuccess ( ) && ! status . IsRejected ( ) {
2020-12-19 11:18:40 -05:00
return status
}
}
return status
}
// addNominatedPods adds pods with equal or greater priority which are nominated
// to run on the node. It returns 1) whether any pod was added, 2) augmented cycleState,
// 3) augmented nodeInfo.
2021-02-26 11:44:05 -05:00
func addNominatedPods ( ctx context . Context , fh framework . Handle , pod * v1 . Pod , state * framework . CycleState , nodeInfo * framework . NodeInfo ) ( bool , * framework . CycleState , * framework . NodeInfo , error ) {
2023-05-05 22:59:23 -04:00
if fh == nil {
2020-12-19 11:18:40 -05:00
// This may happen only in tests.
return false , state , nodeInfo , nil
}
2021-02-26 11:44:05 -05:00
nominatedPodInfos := fh . NominatedPodsForNode ( nodeInfo . Node ( ) . Name )
2021-02-22 09:00:23 -05:00
if len ( nominatedPodInfos ) == 0 {
2020-12-19 11:18:40 -05:00
return false , state , nodeInfo , nil
}
2023-09-13 08:07:33 -04:00
nodeInfoOut := nodeInfo . Snapshot ( )
2020-12-19 11:18:40 -05:00
stateOut := state . Clone ( )
podsAdded := false
2021-02-22 09:00:23 -05:00
for _ , pi := range nominatedPodInfos {
if corev1 . PodPriority ( pi . Pod ) >= corev1 . PodPriority ( pod ) && pi . Pod . UID != pod . UID {
nodeInfoOut . AddPodInfo ( pi )
2021-02-26 11:44:05 -05:00
status := fh . RunPreFilterExtensionAddPod ( ctx , stateOut , pod , pi , nodeInfoOut )
2020-12-19 11:18:40 -05:00
if ! status . IsSuccess ( ) {
return false , state , nodeInfo , status . AsError ( )
}
podsAdded = true
}
}
return podsAdded , stateOut , nodeInfoOut , nil
}
2020-02-02 05:07:01 -05:00
// RunPreScorePlugins runs the set of configured pre-score plugins. If any
2023-02-13 17:53:29 -05:00
// of these plugins returns any status other than Success/Skip, the given pod is rejected.
// When it returns Skip status, other fields in status are just ignored,
// and coupled Score plugin will be skipped in this scheduling cycle.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunPreScorePlugins (
2019-08-28 07:12:02 -04:00
ctx context . Context ,
2020-06-19 05:05:45 -04:00
state * framework . CycleState ,
2019-07-30 23:21:26 -04:00
pod * v1 . Pod ,
nodes [ ] * v1 . Node ,
2020-06-19 05:05:45 -04:00
) ( status * framework . Status ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
2023-08-23 07:03:45 -04:00
skipPlugins := sets . New [ string ] ( )
2020-01-08 23:23:05 -05:00
defer func ( ) {
2023-08-23 07:03:45 -04:00
state . SkipScorePlugins = skipPlugins
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . PreScore , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "PreScore" )
}
2020-02-02 05:07:01 -05:00
for _ , pl := range f . preScorePlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2020-02-15 00:48:45 -05:00
status = f . runPreScorePlugin ( ctx , pl , state , pod , nodes )
2023-02-13 17:53:29 -05:00
if status . IsSkip ( ) {
skipPlugins . Insert ( pl . Name ( ) )
continue
}
2019-07-30 23:21:26 -04:00
if ! status . IsSuccess ( ) {
2021-01-31 04:17:03 -05:00
return framework . AsStatus ( fmt . Errorf ( "running PreScore plugin %q: %w" , pl . Name ( ) , status . AsError ( ) ) )
2019-07-30 23:21:26 -04:00
}
}
return nil
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runPreScorePlugin ( ctx context . Context , pl framework . PreScorePlugin , state * framework . CycleState , pod * v1 . Pod , nodes [ ] * v1 . Node ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2020-02-15 00:48:45 -05:00
return pl . PreScore ( ctx , state , pod , nodes )
2019-10-29 10:54:02 -04:00
}
startTime := time . Now ( )
2020-02-15 00:48:45 -05:00
status := pl . PreScore ( ctx , state , pod , nodes )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . PreScore , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
2022-03-03 12:00:00 -05:00
// RunScorePlugins runs the set of configured scoring plugins.
// It returns a list that stores scores from each plugin and total score for each Node.
2019-07-16 09:19:20 -04:00
// It also returns *Status, which is set to non-success if any of the plugins returns
// a non-success status.
2022-03-03 12:00:00 -05:00
func ( f * frameworkImpl ) RunScorePlugins ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , nodes [ ] * v1 . Node ) ( ns [ ] framework . NodePluginScores , status * framework . Status ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . Score , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2022-03-03 12:00:00 -05:00
allNodePluginScores := make ( [ ] framework . NodePluginScores , len ( nodes ) )
2023-10-31 04:02:16 -04:00
numPlugins := len ( f . scorePlugins )
2023-02-13 17:53:29 -05:00
plugins := make ( [ ] framework . ScorePlugin , 0 , numPlugins )
2023-07-19 22:50:32 -04:00
pluginToNodeScores := make ( map [ string ] framework . NodeScoreList , numPlugins )
2019-07-16 09:19:20 -04:00
for _ , pl := range f . scorePlugins {
2023-02-13 17:53:29 -05:00
if state . SkipScorePlugins . Has ( pl . Name ( ) ) {
continue
}
plugins = append ( plugins , pl )
2023-07-19 22:50:32 -04:00
pluginToNodeScores [ pl . Name ( ) ] = make ( framework . NodeScoreList , len ( nodes ) )
2019-07-16 09:19:20 -04:00
}
2019-08-28 07:12:02 -04:00
ctx , cancel := context . WithCancel ( ctx )
2022-08-12 01:22:40 -04:00
defer cancel ( )
2020-03-31 22:34:13 -04:00
errCh := parallelize . NewErrorChannel ( )
2019-08-19 16:08:14 -04:00
2023-07-19 22:50:32 -04:00
if len ( plugins ) > 0 {
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "Score" )
}
2023-07-19 22:50:32 -04:00
// Run Score method for each node in parallel.
f . Parallelizer ( ) . Until ( ctx , len ( nodes ) , func ( index int ) {
nodeName := nodes [ index ] . Name
2023-11-02 09:36:23 -04:00
logger := logger
if verboseLogs {
logger = klog . LoggerWithValues ( logger , "node" , klog . ObjectRef { Name : nodeName } )
}
2023-07-19 22:50:32 -04:00
for _ , pl := range plugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2023-07-19 22:50:32 -04:00
s , status := f . runScorePlugin ( ctx , pl , state , pod , nodeName )
if ! status . IsSuccess ( ) {
err := fmt . Errorf ( "plugin %q failed with: %w" , pl . Name ( ) , status . AsError ( ) )
errCh . SendErrorWithCancel ( err , cancel )
return
}
pluginToNodeScores [ pl . Name ( ) ] [ index ] = framework . NodeScore {
Name : nodeName ,
Score : s ,
}
2019-08-02 07:24:55 -04:00
}
2023-07-19 22:50:32 -04:00
} , metrics . Score )
if err := errCh . ReceiveError ( ) ; err != nil {
return nil , framework . AsStatus ( fmt . Errorf ( "running Score plugins: %w" , err ) )
2019-07-16 09:19:20 -04:00
}
2023-07-19 22:50:32 -04:00
}
2019-07-16 09:19:20 -04:00
2023-07-19 22:50:32 -04:00
// Run NormalizeScore method for each ScorePlugin in parallel.
f . Parallelizer ( ) . Until ( ctx , len ( plugins ) , func ( index int ) {
pl := plugins [ index ]
2019-10-04 10:59:13 -04:00
if pl . ScoreExtensions ( ) == nil {
2019-10-01 11:59:48 -04:00
return
}
2023-07-19 22:50:32 -04:00
nodeScoreList := pluginToNodeScores [ pl . Name ( ) ]
status := f . runScoreExtension ( ctx , pl , state , pod , nodeScoreList )
2019-10-04 10:25:17 -04:00
if ! status . IsSuccess ( ) {
2020-09-24 09:10:42 -04:00
err := fmt . Errorf ( "plugin %q failed with: %w" , pl . Name ( ) , status . AsError ( ) )
2019-07-29 11:45:01 -04:00
errCh . SendErrorWithCancel ( err , cancel )
2019-08-01 07:59:15 -04:00
return
2019-07-29 11:45:01 -04:00
}
2023-03-06 16:54:01 -05:00
} , metrics . Score )
2019-07-29 11:45:01 -04:00
if err := errCh . ReceiveError ( ) ; err != nil {
2020-09-24 09:10:42 -04:00
return nil , framework . AsStatus ( fmt . Errorf ( "running Normalize on Score plugins: %w" , err ) )
2019-07-29 11:45:01 -04:00
}
2022-03-03 12:00:00 -05:00
// Apply score weight for each ScorePlugin in parallel,
// and then, build allNodePluginScores.
f . Parallelizer ( ) . Until ( ctx , len ( nodes ) , func ( index int ) {
nodePluginScores := framework . NodePluginScores {
Name : nodes [ index ] . Name ,
2023-02-13 17:53:29 -05:00
Scores : make ( [ ] framework . PluginScore , len ( plugins ) ) ,
2022-03-03 12:00:00 -05:00
}
2019-08-09 05:03:55 -04:00
2023-02-13 17:53:29 -05:00
for i , pl := range plugins {
2022-03-03 12:00:00 -05:00
weight := f . scorePluginWeight [ pl . Name ( ) ]
2023-07-19 22:50:32 -04:00
nodeScoreList := pluginToNodeScores [ pl . Name ( ) ]
2022-03-03 12:00:00 -05:00
score := nodeScoreList [ index ] . Score
if score > framework . MaxNodeScore || score < framework . MinNodeScore {
err := fmt . Errorf ( "plugin %q returns an invalid score %v, it should in the range of [%v, %v] after normalizing" , pl . Name ( ) , score , framework . MinNodeScore , framework . MaxNodeScore )
2019-08-09 05:03:55 -04:00
errCh . SendErrorWithCancel ( err , cancel )
return
}
2022-03-03 12:00:00 -05:00
weightedScore := score * int64 ( weight )
nodePluginScores . Scores [ i ] = framework . PluginScore {
Name : pl . Name ( ) ,
Score : weightedScore ,
}
nodePluginScores . TotalScore += weightedScore
2019-07-29 11:45:01 -04:00
}
2022-03-03 12:00:00 -05:00
allNodePluginScores [ index ] = nodePluginScores
2023-03-06 16:54:01 -05:00
} , metrics . Score )
2019-07-29 11:45:01 -04:00
if err := errCh . ReceiveError ( ) ; err != nil {
2020-09-24 09:10:42 -04:00
return nil , framework . AsStatus ( fmt . Errorf ( "applying score defaultWeights on Score plugins: %w" , err ) )
2019-07-29 11:45:01 -04:00
}
2022-03-03 12:00:00 -05:00
return allNodePluginScores , nil
2019-07-29 11:45:01 -04:00
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runScorePlugin ( ctx context . Context , pl framework . ScorePlugin , state * framework . CycleState , pod * v1 . Pod , nodeName string ) ( int64 , * framework . Status ) {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return pl . Score ( ctx , state , pod , nodeName )
}
startTime := time . Now ( )
s , status := pl . Score ( ctx , state , pod , nodeName )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . Score , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return s , status
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runScoreExtension ( ctx context . Context , pl framework . ScorePlugin , state * framework . CycleState , pod * v1 . Pod , nodeScoreList framework . NodeScoreList ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return pl . ScoreExtensions ( ) . NormalizeScore ( ctx , state , pod , nodeScoreList )
}
startTime := time . Now ( )
status := pl . ScoreExtensions ( ) . NormalizeScore ( ctx , state , pod , nodeScoreList )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . ScoreExtensionNormalize , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
2019-08-22 14:07:28 -04:00
// RunPreBindPlugins runs the set of configured prebind plugins. It returns a
2019-03-27 18:21:32 -04:00
// failure (bool) if any of the plugins returns an error. It also returns an
// error containing the rejection message or the error occurred in the plugin.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunPreBindPlugins ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , nodeName string ) ( status * framework . Status ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . PreBind , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "PreBind" )
logger = klog . LoggerWithValues ( logger , "node" , klog . ObjectRef { Name : nodeName } )
}
2019-08-22 14:07:28 -04:00
for _ , pl := range f . preBindPlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2019-10-29 10:54:02 -04:00
status = f . runPreBindPlugin ( ctx , pl , state , pod , nodeName )
2019-03-27 18:21:32 -04:00
if ! status . IsSuccess ( ) {
2023-10-25 08:01:07 -04:00
if status . IsRejected ( ) {
2023-03-22 03:52:25 -04:00
logger . V ( 4 ) . Info ( "Pod rejected by PreBind plugin" , "pod" , klog . KObj ( pod ) , "node" , nodeName , "plugin" , pl . Name ( ) , "status" , status . Message ( ) )
2023-10-25 08:01:07 -04:00
status . SetPlugin ( pl . Name ( ) )
2022-09-09 11:31:23 -04:00
return status
}
2020-09-24 09:10:42 -04:00
err := status . AsError ( )
2023-03-22 03:52:25 -04:00
logger . Error ( err , "Plugin failed" , "plugin" , pl . Name ( ) , "pod" , klog . KObj ( pod ) , "node" , nodeName )
2020-09-24 09:10:42 -04:00
return framework . AsStatus ( fmt . Errorf ( "running PreBind plugin %q: %w" , pl . Name ( ) , err ) )
2019-03-27 18:21:32 -04:00
}
}
return nil
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runPreBindPlugin ( ctx context . Context , pl framework . PreBindPlugin , state * framework . CycleState , pod * v1 . Pod , nodeName string ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return pl . PreBind ( ctx , state , pod , nodeName )
}
startTime := time . Now ( )
status := pl . PreBind ( ctx , state , pod , nodeName )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . PreBind , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
2019-06-23 12:42:28 -04:00
// RunBindPlugins runs the set of configured bind plugins until one returns a non `Skip` status.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunBindPlugins ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , nodeName string ) ( status * framework . Status ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . Bind , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2019-06-23 12:42:28 -04:00
if len ( f . bindPlugins ) == 0 {
2020-06-19 05:05:45 -04:00
return framework . NewStatus ( framework . Skip , "" )
2019-06-23 12:42:28 -04:00
}
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "Bind" )
}
2022-09-09 11:31:23 -04:00
for _ , pl := range f . bindPlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2022-09-09 11:31:23 -04:00
status = f . runBindPlugin ( ctx , pl , state , pod , nodeName )
2022-05-11 04:07:12 -04:00
if status . IsSkip ( ) {
2019-06-23 12:42:28 -04:00
continue
}
if ! status . IsSuccess ( ) {
2023-10-25 08:01:07 -04:00
if status . IsRejected ( ) {
2023-03-22 03:52:25 -04:00
logger . V ( 4 ) . Info ( "Pod rejected by Bind plugin" , "pod" , klog . KObj ( pod ) , "node" , nodeName , "plugin" , pl . Name ( ) , "status" , status . Message ( ) )
2023-10-25 08:01:07 -04:00
status . SetPlugin ( pl . Name ( ) )
2022-09-09 11:31:23 -04:00
return status
}
2020-09-24 09:10:42 -04:00
err := status . AsError ( )
2023-03-22 03:52:25 -04:00
logger . Error ( err , "Plugin Failed" , "plugin" , pl . Name ( ) , "pod" , klog . KObj ( pod ) , "node" , nodeName )
2022-09-09 11:31:23 -04:00
return framework . AsStatus ( fmt . Errorf ( "running Bind plugin %q: %w" , pl . Name ( ) , err ) )
2019-06-23 12:42:28 -04:00
}
return status
}
return status
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runBindPlugin ( ctx context . Context , bp framework . BindPlugin , state * framework . CycleState , pod * v1 . Pod , nodeName string ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return bp . Bind ( ctx , state , pod , nodeName )
}
2019-10-04 10:25:17 -04:00
startTime := time . Now ( )
2019-10-29 10:54:02 -04:00
status := bp . Bind ( ctx , state , pod , nodeName )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . Bind , bp . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
// RunPostBindPlugins runs the set of configured postbind plugins.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunPostBindPlugins ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , nodeName string ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . PostBind , framework . Success . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "PostBind" )
}
2019-08-22 14:02:26 -04:00
for _ , pl := range f . postBindPlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2019-10-29 10:54:02 -04:00
f . runPostBindPlugin ( ctx , pl , state , pod , nodeName )
}
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runPostBindPlugin ( ctx context . Context , pl framework . PostBindPlugin , state * framework . CycleState , pod * v1 . Pod , nodeName string ) {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-08-28 07:12:02 -04:00
pl . PostBind ( ctx , state , pod , nodeName )
2019-10-29 10:54:02 -04:00
return
2019-05-08 07:55:39 -04:00
}
2019-10-29 10:54:02 -04:00
startTime := time . Now ( )
pl . PostBind ( ctx , state , pod , nodeName )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . PostBind , pl . Name ( ) , framework . Success . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-05-08 07:55:39 -04:00
}
2020-06-15 17:52:54 -04:00
// RunReservePluginsReserve runs the Reserve method in the set of configured
// reserve plugins. If any of these plugins returns an error, it does not
// continue running the remaining ones and returns the error. In such a case,
2020-06-22 14:38:29 -04:00
// the pod will not be scheduled and the caller will be expected to call
// RunReservePluginsUnreserve.
2020-06-15 17:52:54 -04:00
func ( f * frameworkImpl ) RunReservePluginsReserve ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , nodeName string ) ( status * framework . Status ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . Reserve , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "Reserve" )
logger = klog . LoggerWithValues ( logger , "node" , klog . ObjectRef { Name : nodeName } )
}
2019-03-27 18:21:32 -04:00
for _ , pl := range f . reservePlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2020-06-15 17:52:54 -04:00
status = f . runReservePluginReserve ( ctx , pl , state , pod , nodeName )
2019-03-27 18:21:32 -04:00
if ! status . IsSuccess ( ) {
2023-10-25 08:01:07 -04:00
if status . IsRejected ( ) {
2023-07-06 22:51:30 -04:00
logger . V ( 4 ) . Info ( "Pod rejected by plugin" , "pod" , klog . KObj ( pod ) , "plugin" , pl . Name ( ) , "status" , status . Message ( ) )
2023-10-25 08:01:07 -04:00
status . SetPlugin ( pl . Name ( ) )
2023-07-06 22:51:30 -04:00
return status
}
2020-09-24 09:10:42 -04:00
err := status . AsError ( )
2023-03-22 03:52:25 -04:00
logger . Error ( err , "Plugin failed" , "plugin" , pl . Name ( ) , "pod" , klog . KObj ( pod ) )
2020-09-24 09:10:42 -04:00
return framework . AsStatus ( fmt . Errorf ( "running Reserve plugin %q: %w" , pl . Name ( ) , err ) )
2019-03-27 18:21:32 -04:00
}
}
return nil
}
2020-06-15 17:52:54 -04:00
func ( f * frameworkImpl ) runReservePluginReserve ( ctx context . Context , pl framework . ReservePlugin , state * framework . CycleState , pod * v1 . Pod , nodeName string ) * framework . Status {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return pl . Reserve ( ctx , state , pod , nodeName )
}
2019-10-04 10:25:17 -04:00
startTime := time . Now ( )
2019-10-29 10:54:02 -04:00
status := pl . Reserve ( ctx , state , pod , nodeName )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . Reserve , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status
}
2020-06-15 17:52:54 -04:00
// RunReservePluginsUnreserve runs the Unreserve method in the set of
// configured reserve plugins.
func ( f * frameworkImpl ) RunReservePluginsUnreserve ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , nodeName string ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . Unreserve , framework . Success . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2020-06-15 17:52:54 -04:00
// Execute the Unreserve operation of each reserve plugin in the
// *reverse* order in which the Reserve operation was executed.
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "Unreserve" )
logger = klog . LoggerWithValues ( logger , "node" , klog . ObjectRef { Name : nodeName } )
}
2020-06-15 17:52:54 -04:00
for i := len ( f . reservePlugins ) - 1 ; i >= 0 ; i -- {
2023-11-02 09:36:23 -04:00
pl := f . reservePlugins [ i ]
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
f . runReservePluginUnreserve ( ctx , pl , state , pod , nodeName )
2019-10-29 10:54:02 -04:00
}
}
2020-06-15 17:52:54 -04:00
func ( f * frameworkImpl ) runReservePluginUnreserve ( ctx context . Context , pl framework . ReservePlugin , state * framework . CycleState , pod * v1 . Pod , nodeName string ) {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-08-28 07:12:02 -04:00
pl . Unreserve ( ctx , state , pod , nodeName )
2019-10-29 10:54:02 -04:00
return
2019-05-04 23:16:14 -04:00
}
2019-10-29 10:54:02 -04:00
startTime := time . Now ( )
pl . Unreserve ( ctx , state , pod , nodeName )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . Unreserve , pl . Name ( ) , framework . Success . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-05-04 23:16:14 -04:00
}
2019-05-10 09:05:59 -04:00
// RunPermitPlugins runs the set of configured permit plugins. If any of these
// plugins returns a status other than "Success" or "Wait", it does not continue
// running the remaining plugins and returns an error. Otherwise, if any of the
2020-02-15 19:28:43 -05:00
// plugins returns "Wait", then this function will create and add waiting pod
// to a map of currently waiting pods and return status with "Wait" code.
// Pod will remain waiting pod for the minimum duration returned by the permit plugins.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) RunPermitPlugins ( ctx context . Context , state * framework . CycleState , pod * v1 . Pod , nodeName string ) ( status * framework . Status ) {
2020-01-08 23:23:05 -05:00
startTime := time . Now ( )
defer func ( ) {
2023-03-06 16:54:01 -05:00
metrics . FrameworkExtensionPointDuration . WithLabelValues ( metrics . Permit , status . Code ( ) . String ( ) , f . profileName ) . Observe ( metrics . SinceInSeconds ( startTime ) )
2020-01-08 23:23:05 -05:00
} ( )
2019-10-10 21:56:13 -04:00
pluginsWaitTime := make ( map [ string ] time . Duration )
2020-06-19 05:05:45 -04:00
statusCode := framework . Success
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
2023-11-02 09:36:23 -04:00
verboseLogs := logger . V ( 4 ) . Enabled ( )
if verboseLogs {
logger = klog . LoggerWithName ( logger , "Permit" )
logger = klog . LoggerWithValues ( logger , "node" , klog . ObjectRef { Name : nodeName } )
}
2019-05-10 09:05:59 -04:00
for _ , pl := range f . permitPlugins {
2023-11-02 09:36:23 -04:00
ctx := ctx
if verboseLogs {
logger := klog . LoggerWithName ( logger , pl . Name ( ) )
ctx = klog . NewContext ( ctx , logger )
}
2019-10-29 10:54:02 -04:00
status , timeout := f . runPermitPlugin ( ctx , pl , state , pod , nodeName )
2019-05-10 09:05:59 -04:00
if ! status . IsSuccess ( ) {
2023-10-25 08:01:07 -04:00
if status . IsRejected ( ) {
2023-03-22 03:52:25 -04:00
logger . V ( 4 ) . Info ( "Pod rejected by plugin" , "pod" , klog . KObj ( pod ) , "plugin" , pl . Name ( ) , "status" , status . Message ( ) )
2023-10-25 08:01:07 -04:00
return status . WithPlugin ( pl . Name ( ) )
2019-05-10 09:05:59 -04:00
}
2022-04-14 03:06:37 -04:00
if status . IsWait ( ) {
2019-10-10 21:56:13 -04:00
// Not allowed to be greater than maxTimeout.
if timeout > maxTimeout {
timeout = maxTimeout
2019-05-10 09:05:59 -04:00
}
2019-10-10 21:56:13 -04:00
pluginsWaitTime [ pl . Name ( ) ] = timeout
2020-06-19 05:05:45 -04:00
statusCode = framework . Wait
2019-05-10 09:05:59 -04:00
} else {
2020-09-24 09:10:42 -04:00
err := status . AsError ( )
2023-03-22 03:52:25 -04:00
logger . Error ( err , "Plugin failed" , "plugin" , pl . Name ( ) , "pod" , klog . KObj ( pod ) )
2023-10-25 08:01:07 -04:00
return framework . AsStatus ( fmt . Errorf ( "running Permit plugin %q: %w" , pl . Name ( ) , err ) ) . WithPlugin ( pl . Name ( ) )
2019-05-10 09:05:59 -04:00
}
}
}
2020-06-19 05:05:45 -04:00
if statusCode == framework . Wait {
2020-02-15 19:28:43 -05:00
waitingPod := newWaitingPod ( pod , pluginsWaitTime )
f . waitingPods . add ( waitingPod )
msg := fmt . Sprintf ( "one or more plugins asked to wait and no plugin rejected pod %q" , pod . Name )
2023-03-22 03:52:25 -04:00
logger . V ( 4 ) . Info ( "One or more plugins asked to wait and no plugin rejected pod" , "pod" , klog . KObj ( pod ) )
2020-06-19 05:05:45 -04:00
return framework . NewStatus ( framework . Wait , msg )
2019-05-10 09:05:59 -04:00
}
return nil
}
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) runPermitPlugin ( ctx context . Context , pl framework . PermitPlugin , state * framework . CycleState , pod * v1 . Pod , nodeName string ) ( * framework . Status , time . Duration ) {
2020-01-08 23:23:05 -05:00
if ! state . ShouldRecordPluginMetrics ( ) {
2019-10-29 10:54:02 -04:00
return pl . Permit ( ctx , state , pod , nodeName )
}
startTime := time . Now ( )
status , timeout := pl . Permit ( ctx , state , pod , nodeName )
2023-03-06 16:54:01 -05:00
f . metricsRecorder . ObservePluginDurationAsync ( metrics . Permit , pl . Name ( ) , status . Code ( ) . String ( ) , metrics . SinceInSeconds ( startTime ) )
2019-10-29 10:54:02 -04:00
return status , timeout
}
2020-02-15 19:28:43 -05:00
// WaitOnPermit will block, if the pod is a waiting pod, until the waiting pod is rejected or allowed.
2021-01-13 19:39:55 -05:00
func ( f * frameworkImpl ) WaitOnPermit ( ctx context . Context , pod * v1 . Pod ) * framework . Status {
2020-02-15 19:28:43 -05:00
waitingPod := f . waitingPods . get ( pod . UID )
if waitingPod == nil {
return nil
}
defer f . waitingPods . remove ( pod . UID )
2023-03-22 03:52:25 -04:00
logger := klog . FromContext ( ctx )
logger . V ( 4 ) . Info ( "Pod waiting on permit" , "pod" , klog . KObj ( pod ) )
2020-02-15 19:28:43 -05:00
startTime := time . Now ( )
s := <- waitingPod . s
metrics . PermitWaitDuration . WithLabelValues ( s . Code ( ) . String ( ) ) . Observe ( metrics . SinceInSeconds ( startTime ) )
if ! s . IsSuccess ( ) {
2023-10-25 08:01:07 -04:00
if s . IsRejected ( ) {
2023-03-22 03:52:25 -04:00
logger . V ( 4 ) . Info ( "Pod rejected while waiting on permit" , "pod" , klog . KObj ( pod ) , "status" , s . Message ( ) )
2021-01-13 19:39:55 -05:00
return s
2020-02-15 19:28:43 -05:00
}
2020-09-24 09:10:42 -04:00
err := s . AsError ( )
2023-03-22 03:52:25 -04:00
logger . Error ( err , "Failed waiting on permit for pod" , "pod" , klog . KObj ( pod ) )
2023-10-25 08:01:07 -04:00
return framework . AsStatus ( fmt . Errorf ( "waiting on permit for pod: %w" , err ) ) . WithPlugin ( s . Plugin ( ) )
2020-02-15 19:28:43 -05:00
}
return nil
}
2019-10-24 18:30:21 -04:00
// SnapshotSharedLister returns the scheduler's SharedLister of the latest NodeInfo
// snapshot. The snapshot is taken at the beginning of a scheduling cycle and remains
// unchanged until a pod finishes "Reserve". There is no guarantee that the information
// remains unchanged after "Reserve".
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) SnapshotSharedLister ( ) framework . SharedLister {
2019-11-05 21:25:07 -05:00
return f . snapshotSharedLister
2019-03-27 18:21:32 -04:00
}
2019-05-10 09:05:59 -04:00
// IterateOverWaitingPods acquires a read lock and iterates over the WaitingPods map.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) IterateOverWaitingPods ( callback func ( framework . WaitingPod ) ) {
2019-05-10 09:05:59 -04:00
f . waitingPods . iterate ( callback )
}
// GetWaitingPod returns a reference to a WaitingPod given its UID.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) GetWaitingPod ( uid types . UID ) framework . WaitingPod {
2020-02-15 19:28:43 -05:00
if wp := f . waitingPods . get ( uid ) ; wp != nil {
return wp
}
return nil // Returning nil instead of *waitingPod(nil).
2019-05-10 09:05:59 -04:00
}
2019-05-04 06:29:30 -04:00
2019-11-05 09:04:44 -05:00
// RejectWaitingPod rejects a WaitingPod given its UID.
2021-07-19 18:46:55 -04:00
// The returned value indicates if the given pod is waiting or not.
func ( f * frameworkImpl ) RejectWaitingPod ( uid types . UID ) bool {
if waitingPod := f . waitingPods . get ( uid ) ; waitingPod != nil {
2021-01-13 19:39:55 -05:00
waitingPod . Reject ( "" , "removed" )
2021-07-19 18:46:55 -04:00
return true
2019-11-05 09:04:44 -05:00
}
2021-07-19 18:46:55 -04:00
return false
2019-11-05 09:04:44 -05:00
}
2019-10-16 21:24:33 -04:00
// HasFilterPlugins returns true if at least one filter plugin is defined.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) HasFilterPlugins ( ) bool {
2019-10-16 21:24:33 -04:00
return len ( f . filterPlugins ) > 0
}
2020-06-22 20:22:27 -04:00
// HasPostFilterPlugins returns true if at least one postFilter plugin is defined.
func ( f * frameworkImpl ) HasPostFilterPlugins ( ) bool {
return len ( f . postFilterPlugins ) > 0
}
2019-10-29 05:25:35 -04:00
// HasScorePlugins returns true if at least one score plugin is defined.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) HasScorePlugins ( ) bool {
2019-10-29 05:25:35 -04:00
return len ( f . scorePlugins ) > 0
}
2019-10-04 17:40:21 -04:00
// ListPlugins returns a map of extension point name to plugin names configured at each extension
2020-05-26 12:00:22 -04:00
// point. Returns nil if no plugins where configured.
2021-06-10 08:45:49 -04:00
func ( f * frameworkImpl ) ListPlugins ( ) * config . Plugins {
m := config . Plugins { }
2019-10-05 20:31:51 -04:00
2021-06-10 08:45:49 -04:00
for _ , e := range f . getExtensionPoints ( & m ) {
2019-10-05 22:30:50 -04:00
plugins := reflect . ValueOf ( e . slicePtr ) . Elem ( )
2019-10-05 20:31:51 -04:00
extName := plugins . Type ( ) . Elem ( ) . Name ( )
var cfgs [ ] config . Plugin
2019-10-04 17:40:21 -04:00
for i := 0 ; i < plugins . Len ( ) ; i ++ {
2020-06-19 05:05:45 -04:00
name := plugins . Index ( i ) . Interface ( ) . ( framework . Plugin ) . Name ( )
2019-10-05 20:31:51 -04:00
p := config . Plugin { Name : name }
if extName == "ScorePlugin" {
// Weights apply only to score plugins.
2021-03-29 04:34:10 -04:00
p . Weight = int32 ( f . scorePluginWeight [ name ] )
2019-10-05 20:31:51 -04:00
}
cfgs = append ( cfgs , p )
2019-10-04 17:40:21 -04:00
}
2019-10-05 20:31:51 -04:00
if len ( cfgs ) > 0 {
2021-06-10 08:45:49 -04:00
e . plugins . Enabled = cfgs
2019-10-04 17:40:21 -04:00
}
2019-05-04 06:29:30 -04:00
}
2021-06-10 08:45:49 -04:00
return & m
2019-05-04 06:29:30 -04:00
}
2019-08-19 05:46:15 -04:00
// ClientSet returns a kubernetes clientset.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) ClientSet ( ) clientset . Interface {
2019-08-19 05:46:15 -04:00
return f . clientSet
}
2021-03-29 15:27:27 -04:00
// KubeConfig returns a kubernetes config.
func ( f * frameworkImpl ) KubeConfig ( ) * restclient . Config {
return f . kubeConfig
}
2020-06-10 18:51:32 -04:00
// EventRecorder returns an event recorder.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) EventRecorder ( ) events . EventRecorder {
2020-06-10 18:51:32 -04:00
return f . eventRecorder
}
2019-10-09 02:49:56 -04:00
// SharedInformerFactory returns a shared informer factory.
2020-06-19 05:05:45 -04:00
func ( f * frameworkImpl ) SharedInformerFactory ( ) informers . SharedInformerFactory {
2019-10-09 02:49:56 -04:00
return f . informerFactory
}
2023-03-27 03:46:13 -04:00
func ( f * frameworkImpl ) pluginsNeeded ( plugins * config . Plugins ) sets . Set [ string ] {
pgSet := sets . Set [ string ] { }
2019-05-04 06:29:30 -04:00
if plugins == nil {
2021-12-14 22:59:56 -05:00
return pgSet
2019-05-04 06:29:30 -04:00
}
2021-06-10 08:45:49 -04:00
find := func ( pgs * config . PluginSet ) {
2019-05-04 06:29:30 -04:00
for _ , pg := range pgs . Enabled {
2021-12-14 22:59:56 -05:00
pgSet . Insert ( pg . Name )
2019-05-04 06:29:30 -04:00
}
}
2021-12-14 22:59:56 -05:00
2019-10-04 17:40:21 -04:00
for _ , e := range f . getExtensionPoints ( plugins ) {
find ( e . plugins )
}
2021-10-11 13:47:23 -04:00
// Parse MultiPoint separately since they are not returned by f.getExtensionPoints()
find ( & plugins . MultiPoint )
2021-12-14 22:59:56 -05:00
return pgSet
2019-05-04 06:29:30 -04:00
}
2020-06-05 16:02:45 -04:00
2020-10-18 22:43:50 -04:00
// ProfileName returns the profile name associated to this framework.
func ( f * frameworkImpl ) ProfileName ( ) string {
return f . profileName
}
2021-03-01 09:20:18 -05:00
2022-09-16 16:18:12 -04:00
// PercentageOfNodesToScore returns percentageOfNodesToScore associated to a profile.
func ( f * frameworkImpl ) PercentageOfNodesToScore ( ) * int32 {
return f . percentageOfNodesToScore
}
2021-03-01 09:20:18 -05:00
// Parallelizer returns a parallelizer holding parallelism for scheduler.
func ( f * frameworkImpl ) Parallelizer ( ) parallelize . Parallelizer {
return f . parallelizer
}