scheduler: merge Reserve and Unreserve plugins

Previously, separate interfaces were defined for Reserve and Unreserve
plugins. However, in nearly all cases, a plugin that allocates a
resource using Reserve will likely want to register itself for Unreserve
as well in order to free the allocated resource at the end of a failed
scheduling/binding cycle. Having separate plugins for Reserve and
Unreserve also adds unnecessary config toil. To that end, this patch
aims to merge the two plugins into a single interface called a
ReservePlugin that requires implementing both the Reserve and Unreserve
methods.
This commit is contained in:
Adhityaa Chandrasekar 2020-06-15 21:52:54 +00:00
parent 8adcd7978e
commit ec83143342
23 changed files with 243 additions and 288 deletions

View File

@ -200,7 +200,6 @@ profiles:
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
} }
@ -234,7 +233,6 @@ profiles:
"QueueSortPlugin": {{Name: "PrioritySort"}}, "QueueSortPlugin": {{Name: "PrioritySort"}},
"ScorePlugin": {{Name: "InterPodAffinity", Weight: 1}, {Name: "TaintToleration", Weight: 1}}, "ScorePlugin": {{Name: "InterPodAffinity", Weight: 1}, {Name: "TaintToleration", Weight: 1}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
}, },
@ -251,7 +249,6 @@ profiles:
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"QueueSortPlugin": {{Name: "PrioritySort"}}, "QueueSortPlugin": {{Name: "PrioritySort"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
}, },
@ -333,7 +330,6 @@ profiles:
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
}, },

View File

@ -142,11 +142,6 @@ func getDefaultConfig() *schedulerapi.Plugins {
{Name: volumebinding.Name}, {Name: volumebinding.Name},
}, },
}, },
Unreserve: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name},
},
},
PreBind: &schedulerapi.PluginSet{ PreBind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{ Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name}, {Name: volumebinding.Name},

View File

@ -112,11 +112,6 @@ func TestClusterAutoscalerProvider(t *testing.T) {
{Name: volumebinding.Name}, {Name: volumebinding.Name},
}, },
}, },
Unreserve: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name},
},
},
PreBind: &schedulerapi.PluginSet{ PreBind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{ Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name}, {Name: volumebinding.Name},
@ -209,11 +204,6 @@ func TestApplyFeatureGates(t *testing.T) {
{Name: volumebinding.Name}, {Name: volumebinding.Name},
}, },
}, },
Unreserve: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name},
},
},
PreBind: &schedulerapi.PluginSet{ PreBind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{ Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name}, {Name: volumebinding.Name},
@ -292,11 +282,6 @@ func TestApplyFeatureGates(t *testing.T) {
{Name: volumebinding.Name}, {Name: volumebinding.Name},
}, },
}, },
Unreserve: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name},
},
},
PreBind: &schedulerapi.PluginSet{ PreBind: &schedulerapi.PluginSet{
Enabled: []schedulerapi.Plugin{ Enabled: []schedulerapi.Plugin{
{Name: volumebinding.Name}, {Name: volumebinding.Name},

View File

@ -704,7 +704,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
wantExtenders: []config.Extender{{ wantExtenders: []config.Extender{{
@ -811,7 +810,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
wantExtenders: []config.Extender{{ wantExtenders: []config.Extender{{
@ -931,7 +929,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
wantExtenders: []config.Extender{{ wantExtenders: []config.Extender{{
@ -1053,7 +1050,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
wantExtenders: []config.Extender{{ wantExtenders: []config.Extender{{
@ -1175,7 +1171,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
wantExtenders: []config.Extender{{ wantExtenders: []config.Extender{{
@ -1301,7 +1296,6 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
}, },
wantExtenders: []config.Extender{{ wantExtenders: []config.Extender{{
@ -1430,7 +1424,6 @@ func TestAlgorithmProviderCompatibility(t *testing.T) {
}, },
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
} }
@ -1500,7 +1493,6 @@ func TestAlgorithmProviderCompatibility(t *testing.T) {
{Name: "DefaultPodTopologySpread", Weight: 1}, {Name: "DefaultPodTopologySpread", Weight: 1},
}, },
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
}, },
@ -1591,7 +1583,6 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
{Name: "DefaultPodTopologySpread", Weight: 1}, {Name: "DefaultPodTopologySpread", Weight: 1},
}, },
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
} }
@ -1812,11 +1803,6 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
{Name: "VolumeBinding"}, {Name: "VolumeBinding"},
}, },
}, },
Unreserve: &config.PluginSet{
Disabled: []config.Plugin{
{Name: "VolumeBinding"},
},
},
}, },
wantPlugins: map[string][]config.Plugin{ wantPlugins: map[string][]config.Plugin{
"QueueSortPlugin": { "QueueSortPlugin": {
@ -1941,7 +1927,6 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
{Name: "NodeResourcesBalancedAllocation", Weight: 24}, {Name: "NodeResourcesBalancedAllocation", Weight: 24},
}, },
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
}, },

View File

@ -192,7 +192,8 @@ type Plugins struct {
// Score is a list of plugins that should be invoked when ranking nodes that have passed the filtering phase. // Score is a list of plugins that should be invoked when ranking nodes that have passed the filtering phase.
Score *PluginSet Score *PluginSet
// Reserve is a list of plugins invoked when reserving a node to run the pod. // Reserve is a list of plugins invoked when reserving/unreserving resources
// after a node is assigned to run the pod.
Reserve *PluginSet Reserve *PluginSet
// Permit is a list of plugins that control binding of a Pod. These plugins can prevent or delay binding of a Pod. // Permit is a list of plugins that control binding of a Pod. These plugins can prevent or delay binding of a Pod.
@ -207,9 +208,6 @@ type Plugins struct {
// PostBind is a list of plugins that should be invoked after a pod is successfully bound. // PostBind is a list of plugins that should be invoked after a pod is successfully bound.
PostBind *PluginSet PostBind *PluginSet
// Unreserve is a list of plugins invoked when a pod that was previously reserved is rejected in a later phase.
Unreserve *PluginSet
} }
// PluginSet specifies enabled and disabled plugins for an extension point. // PluginSet specifies enabled and disabled plugins for an extension point.
@ -288,7 +286,6 @@ func (p *Plugins) Append(src *Plugins) {
p.PreBind = appendPluginSet(p.PreBind, src.PreBind) p.PreBind = appendPluginSet(p.PreBind, src.PreBind)
p.Bind = appendPluginSet(p.Bind, src.Bind) p.Bind = appendPluginSet(p.Bind, src.Bind)
p.PostBind = appendPluginSet(p.PostBind, src.PostBind) p.PostBind = appendPluginSet(p.PostBind, src.PostBind)
p.Unreserve = appendPluginSet(p.Unreserve, src.Unreserve)
} }
// Apply merges the plugin configuration from custom plugins, handling disabled sets. // Apply merges the plugin configuration from custom plugins, handling disabled sets.
@ -308,7 +305,6 @@ func (p *Plugins) Apply(customPlugins *Plugins) {
p.PreBind = mergePluginSets(p.PreBind, customPlugins.PreBind) p.PreBind = mergePluginSets(p.PreBind, customPlugins.PreBind)
p.Bind = mergePluginSets(p.Bind, customPlugins.Bind) p.Bind = mergePluginSets(p.Bind, customPlugins.Bind)
p.PostBind = mergePluginSets(p.PostBind, customPlugins.PostBind) p.PostBind = mergePluginSets(p.PostBind, customPlugins.PostBind)
p.Unreserve = mergePluginSets(p.Unreserve, customPlugins.Unreserve)
} }
func mergePluginSets(defaultPluginSet, customPluginSet *PluginSet) *PluginSet { func mergePluginSets(defaultPluginSet, customPluginSet *PluginSet) *PluginSet {

View File

@ -64,7 +64,6 @@ func TestPluginsAppend(t *testing.T) {
PreBind: &PluginSet{}, PreBind: &PluginSet{},
Bind: &PluginSet{}, Bind: &PluginSet{},
PostBind: &PluginSet{}, PostBind: &PluginSet{},
Unreserve: &PluginSet{},
}, },
}, },
{ {
@ -126,7 +125,6 @@ func TestPluginsApply(t *testing.T) {
PreBind: &PluginSet{Enabled: []Plugin{}}, PreBind: &PluginSet{Enabled: []Plugin{}},
Bind: &PluginSet{Enabled: []Plugin{}}, Bind: &PluginSet{Enabled: []Plugin{}},
PostBind: &PluginSet{Enabled: []Plugin{}}, PostBind: &PluginSet{Enabled: []Plugin{}},
Unreserve: &PluginSet{Enabled: []Plugin{}},
}, },
}, },
{ {
@ -168,7 +166,6 @@ func TestPluginsApply(t *testing.T) {
PreBind: &PluginSet{Enabled: []Plugin{}}, PreBind: &PluginSet{Enabled: []Plugin{}},
Bind: &PluginSet{Enabled: []Plugin{}}, Bind: &PluginSet{Enabled: []Plugin{}},
PostBind: &PluginSet{Enabled: []Plugin{}}, PostBind: &PluginSet{Enabled: []Plugin{}},
Unreserve: &PluginSet{Enabled: []Plugin{}},
}, },
}, },
{ {
@ -211,7 +208,6 @@ func TestPluginsApply(t *testing.T) {
PreBind: &PluginSet{Enabled: []Plugin{}}, PreBind: &PluginSet{Enabled: []Plugin{}},
Bind: &PluginSet{Enabled: []Plugin{}}, Bind: &PluginSet{Enabled: []Plugin{}},
PostBind: &PluginSet{Enabled: []Plugin{}}, PostBind: &PluginSet{Enabled: []Plugin{}},
Unreserve: &PluginSet{Enabled: []Plugin{}},
}, },
}, },
{ {
@ -252,7 +248,6 @@ func TestPluginsApply(t *testing.T) {
PreBind: &PluginSet{Enabled: []Plugin{}}, PreBind: &PluginSet{Enabled: []Plugin{}},
Bind: &PluginSet{Enabled: []Plugin{}}, Bind: &PluginSet{Enabled: []Plugin{}},
PostBind: &PluginSet{Enabled: []Plugin{}}, PostBind: &PluginSet{Enabled: []Plugin{}},
Unreserve: &PluginSet{Enabled: []Plugin{}},
}, },
}, },
{ {
@ -282,7 +277,6 @@ func TestPluginsApply(t *testing.T) {
PreBind: nil, PreBind: nil,
Bind: nil, Bind: nil,
PostBind: nil, PostBind: nil,
Unreserve: nil,
}, },
}, },
} }

View File

@ -740,15 +740,6 @@ func autoConvert_v1beta1_Plugins_To_config_Plugins(in *v1beta1.Plugins, out *con
} else { } else {
out.PostBind = nil out.PostBind = nil
} }
if in.Unreserve != nil {
in, out := &in.Unreserve, &out.Unreserve
*out = new(config.PluginSet)
if err := Convert_v1beta1_PluginSet_To_config_PluginSet(*in, *out, s); err != nil {
return err
}
} else {
out.Unreserve = nil
}
return nil return nil
} }
@ -857,15 +848,6 @@ func autoConvert_config_Plugins_To_v1beta1_Plugins(in *config.Plugins, out *v1be
} else { } else {
out.PostBind = nil out.PostBind = nil
} }
if in.Unreserve != nil {
in, out := &in.Unreserve, &out.Unreserve
*out = new(v1beta1.PluginSet)
if err := Convert_config_PluginSet_To_v1beta1_PluginSet(*in, *out, s); err != nil {
return err
}
} else {
out.Unreserve = nil
}
return nil return nil
} }

View File

@ -486,11 +486,6 @@ func (in *Plugins) DeepCopyInto(out *Plugins) {
*out = new(PluginSet) *out = new(PluginSet)
(*in).DeepCopyInto(*out) (*in).DeepCopyInto(*out)
} }
if in.Unreserve != nil {
in, out := &in.Unreserve, &out.Unreserve
*out = new(PluginSet)
(*in).DeepCopyInto(*out)
}
return return
} }

View File

@ -50,7 +50,7 @@ func (s *stateData) Clone() framework.StateData {
return copy return copy
} }
// Reserve is the functions invoked by the framework at "reserve" extension point. // Reserve is the function invoked by the framework at "reserve" extension point.
func (mc CommunicatingPlugin) Reserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status { func (mc CommunicatingPlugin) Reserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
if pod == nil { if pod == nil {
return framework.NewStatus(framework.Error, "pod cannot be nil") return framework.NewStatus(framework.Error, "pod cannot be nil")
@ -63,7 +63,20 @@ func (mc CommunicatingPlugin) Reserve(ctx context.Context, state *framework.Cycl
return nil return nil
} }
// PreBind is the functions invoked by the framework at "prebind" extension point. // Unreserve is the function invoked by the framework when any error happens
// during "reserve" extension point or later.
func (mc CommunicatingPlugin) Unreserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) {
if pod.Name == "my-test-pod" {
state.Lock()
// The pod is at the end of its lifecycle -- let's clean up the allocated
// resources. In this case, our clean up is simply deleting the key written
// in the Reserve operation.
state.Delete(framework.StateKey(pod.Name))
state.Unlock()
}
}
// PreBind is the function invoked by the framework at "prebind" extension point.
func (mc CommunicatingPlugin) PreBind(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status { func (mc CommunicatingPlugin) PreBind(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
if pod == nil { if pod == nil {
return framework.NewStatus(framework.Error, "pod cannot be nil") return framework.NewStatus(framework.Error, "pod cannot be nil")

View File

@ -31,8 +31,7 @@ import (
// This plugin is stateful. It receives arguments at initialization (NewMultipointPlugin) // This plugin is stateful. It receives arguments at initialization (NewMultipointPlugin)
// and changes its state when it is executed. // and changes its state when it is executed.
type MultipointExample struct { type MultipointExample struct {
mpState map[int]string executionPoints []string
numRuns int
mu sync.RWMutex mu sync.RWMutex
} }
@ -47,19 +46,35 @@ func (mp *MultipointExample) Name() string {
return Name return Name
} }
// Reserve is the functions invoked by the framework at "reserve" extension point. // Reserve is the function invoked by the framework at "reserve" extension
// point. In this trivial example, the Reserve method allocates an array of
// strings.
func (mp *MultipointExample) Reserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status { func (mp *MultipointExample) Reserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
// Reserve is not called concurrently, and so we don't need to lock. // Reserve is not called concurrently, and so we don't need to lock.
mp.numRuns++ mp.executionPoints = append(mp.executionPoints, "reserve")
return nil return nil
} }
// PreBind is the functions invoked by the framework at "prebind" extension point. // Unreserve is the function invoked by the framework when any error happens
// during "reserve" extension point or later. In this example, the Unreserve
// method loses its reference to the string slice, allowing it to be garbage
// collected, and thereby "unallocating" the reserved resources.
func (mp *MultipointExample) Unreserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) {
// Unlike Reserve, the Unreserve method may be called concurrently since
// there is no guarantee that there will only one unreserve operation at any
// given point in time (for example, during the binding cycle).
mp.mu.Lock()
defer mp.mu.Unlock()
mp.executionPoints = nil
}
// PreBind is the function invoked by the framework at "prebind" extension
// point.
func (mp *MultipointExample) PreBind(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status { func (mp *MultipointExample) PreBind(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
// PreBind could be called concurrently for different pods. // PreBind could be called concurrently for different pods.
mp.mu.Lock() mp.mu.Lock()
defer mp.mu.Unlock() defer mp.mu.Unlock()
mp.numRuns++ mp.executionPoints = append(mp.executionPoints, "pre-bind")
if pod == nil { if pod == nil {
return framework.NewStatus(framework.Error, "pod must not be nil") return framework.NewStatus(framework.Error, "pod must not be nil")
} }
@ -72,8 +87,6 @@ func New(config *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin
klog.Error("MultipointExample configuration cannot be empty") klog.Error("MultipointExample configuration cannot be empty")
return nil, fmt.Errorf("MultipointExample configuration cannot be empty") return nil, fmt.Errorf("MultipointExample configuration cannot be empty")
} }
mp := MultipointExample{ mp := MultipointExample{}
mpState: make(map[int]string),
}
return &mp, nil return &mp, nil
} }

View File

@ -273,7 +273,6 @@ func NewLegacyRegistry() *LegacyRegistry {
plugins.Filter = appendToPluginSet(plugins.Filter, volumebinding.Name, nil) plugins.Filter = appendToPluginSet(plugins.Filter, volumebinding.Name, nil)
plugins.Reserve = appendToPluginSet(plugins.Reserve, volumebinding.Name, nil) plugins.Reserve = appendToPluginSet(plugins.Reserve, volumebinding.Name, nil)
plugins.PreBind = appendToPluginSet(plugins.PreBind, volumebinding.Name, nil) plugins.PreBind = appendToPluginSet(plugins.PreBind, volumebinding.Name, nil)
plugins.Unreserve = appendToPluginSet(plugins.Unreserve, volumebinding.Name, nil)
return return
}) })
registry.registerPredicateConfigProducer(NoDiskConflictPred, registry.registerPredicateConfigProducer(NoDiskConflictPred,

View File

@ -115,7 +115,6 @@ func TestRegisterConfigProducers(t *testing.T) {
PreBind: &config.PluginSet{}, PreBind: &config.PluginSet{},
Bind: &config.PluginSet{}, Bind: &config.PluginSet{},
PostBind: &config.PluginSet{}, PostBind: &config.PluginSet{},
Unreserve: &config.PluginSet{},
} }
if diff := cmp.Diff(wantPlugins, gotPlugins); diff != "" { if diff := cmp.Diff(wantPlugins, gotPlugins); diff != "" {

View File

@ -66,7 +66,6 @@ var _ framework.PreFilterPlugin = &VolumeBinding{}
var _ framework.FilterPlugin = &VolumeBinding{} var _ framework.FilterPlugin = &VolumeBinding{}
var _ framework.ReservePlugin = &VolumeBinding{} var _ framework.ReservePlugin = &VolumeBinding{}
var _ framework.PreBindPlugin = &VolumeBinding{} var _ framework.PreBindPlugin = &VolumeBinding{}
var _ framework.UnreservePlugin = &VolumeBinding{}
// Name is the name of the plugin used in Registry and configurations. // Name is the name of the plugin used in Registry and configurations.
const Name = "VolumeBinding" const Name = "VolumeBinding"

View File

@ -77,7 +77,6 @@ type frameworkImpl struct {
preBindPlugins []framework.PreBindPlugin preBindPlugins []framework.PreBindPlugin
bindPlugins []framework.BindPlugin bindPlugins []framework.BindPlugin
postBindPlugins []framework.PostBindPlugin postBindPlugins []framework.PostBindPlugin
unreservePlugins []framework.UnreservePlugin
permitPlugins []framework.PermitPlugin permitPlugins []framework.PermitPlugin
clientSet clientset.Interface clientSet clientset.Interface
@ -116,7 +115,6 @@ func (f *frameworkImpl) getExtensionPoints(plugins *config.Plugins) []extensionP
{plugins.PreBind, &f.preBindPlugins}, {plugins.PreBind, &f.preBindPlugins},
{plugins.Bind, &f.bindPlugins}, {plugins.Bind, &f.bindPlugins},
{plugins.PostBind, &f.postBindPlugins}, {plugins.PostBind, &f.postBindPlugins},
{plugins.Unreserve, &f.unreservePlugins},
{plugins.Permit, &f.permitPlugins}, {plugins.Permit, &f.permitPlugins},
{plugins.QueueSort, &f.queueSortPlugins}, {plugins.QueueSort, &f.queueSortPlugins},
} }
@ -787,18 +785,19 @@ func (f *frameworkImpl) runPostBindPlugin(ctx context.Context, pl framework.Post
f.metricsRecorder.observePluginDurationAsync(postBind, pl.Name(), nil, metrics.SinceInSeconds(startTime)) f.metricsRecorder.observePluginDurationAsync(postBind, pl.Name(), nil, metrics.SinceInSeconds(startTime))
} }
// RunReservePlugins runs the set of configured reserve plugins. If any of these // RunReservePluginsReserve runs the Reserve method in the set of configured
// plugins returns an error, it does not continue running the remaining ones and // reserve plugins. If any of these plugins returns an error, it does not
// returns the error. In such case, pod will not be scheduled. // continue running the remaining ones and returns the error. In such a case,
func (f *frameworkImpl) RunReservePlugins(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (status *framework.Status) { // the pod will not be scheduled.
func (f *frameworkImpl) RunReservePluginsReserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (status *framework.Status) {
startTime := time.Now() startTime := time.Now()
defer func() { defer func() {
metrics.FrameworkExtensionPointDuration.WithLabelValues(reserve, status.Code().String(), f.profileName).Observe(metrics.SinceInSeconds(startTime)) metrics.FrameworkExtensionPointDuration.WithLabelValues(reserve, status.Code().String(), f.profileName).Observe(metrics.SinceInSeconds(startTime))
}() }()
for _, pl := range f.reservePlugins { for _, pl := range f.reservePlugins {
status = f.runReservePlugin(ctx, pl, state, pod, nodeName) status = f.runReservePluginReserve(ctx, pl, state, pod, nodeName)
if !status.IsSuccess() { if !status.IsSuccess() {
msg := fmt.Sprintf("error while running %q reserve plugin for pod %q: %v", pl.Name(), pod.Name, status.Message()) msg := fmt.Sprintf("error while running Reserve in %q reserve plugin for pod %q: %v", pl.Name(), pod.Name, status.Message())
klog.Error(msg) klog.Error(msg)
return framework.NewStatus(framework.Error, msg) return framework.NewStatus(framework.Error, msg)
} }
@ -806,7 +805,7 @@ func (f *frameworkImpl) RunReservePlugins(ctx context.Context, state *framework.
return nil return nil
} }
func (f *frameworkImpl) runReservePlugin(ctx context.Context, pl framework.ReservePlugin, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status { func (f *frameworkImpl) runReservePluginReserve(ctx context.Context, pl framework.ReservePlugin, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
if !state.ShouldRecordPluginMetrics() { if !state.ShouldRecordPluginMetrics() {
return pl.Reserve(ctx, state, pod, nodeName) return pl.Reserve(ctx, state, pod, nodeName)
} }
@ -816,18 +815,21 @@ func (f *frameworkImpl) runReservePlugin(ctx context.Context, pl framework.Reser
return status return status
} }
// RunUnreservePlugins runs the set of configured unreserve plugins. // RunReservePluginsUnreserve runs the Unreserve method in the set of
func (f *frameworkImpl) RunUnreservePlugins(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) { // configured reserve plugins.
func (f *frameworkImpl) RunReservePluginsUnreserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) {
startTime := time.Now() startTime := time.Now()
defer func() { defer func() {
metrics.FrameworkExtensionPointDuration.WithLabelValues(unreserve, framework.Success.String(), f.profileName).Observe(metrics.SinceInSeconds(startTime)) metrics.FrameworkExtensionPointDuration.WithLabelValues(unreserve, framework.Success.String(), f.profileName).Observe(metrics.SinceInSeconds(startTime))
}() }()
for _, pl := range f.unreservePlugins { // Execute the Unreserve operation of each reserve plugin in the
f.runUnreservePlugin(ctx, pl, state, pod, nodeName) // *reverse* order in which the Reserve operation was executed.
for i := len(f.reservePlugins) - 1; i >= 0; i-- {
f.runReservePluginUnreserve(ctx, f.reservePlugins[i], state, pod, nodeName)
} }
} }
func (f *frameworkImpl) runUnreservePlugin(ctx context.Context, pl framework.UnreservePlugin, state *framework.CycleState, pod *v1.Pod, nodeName string) { func (f *frameworkImpl) runReservePluginUnreserve(ctx context.Context, pl framework.ReservePlugin, state *framework.CycleState, pod *v1.Pod, nodeName string) {
if !state.ShouldRecordPluginMetrics() { if !state.ShouldRecordPluginMetrics() {
pl.Unreserve(ctx, state, pod, nodeName) pl.Unreserve(ctx, state, pod, nodeName)
return return

View File

@ -184,6 +184,9 @@ func (pl *TestPlugin) Reserve(ctx context.Context, state *v1alpha1.CycleState, p
return v1alpha1.NewStatus(v1alpha1.Code(pl.inj.ReserveStatus), "injected status") return v1alpha1.NewStatus(v1alpha1.Code(pl.inj.ReserveStatus), "injected status")
} }
func (pl *TestPlugin) Unreserve(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) {
}
func (pl *TestPlugin) PreBind(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) *v1alpha1.Status { func (pl *TestPlugin) PreBind(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) *v1alpha1.Status {
return v1alpha1.NewStatus(v1alpha1.Code(pl.inj.PreBindStatus), "injected status") return v1alpha1.NewStatus(v1alpha1.Code(pl.inj.PreBindStatus), "injected status")
} }
@ -191,9 +194,6 @@ func (pl *TestPlugin) PreBind(ctx context.Context, state *v1alpha1.CycleState, p
func (pl *TestPlugin) PostBind(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) { func (pl *TestPlugin) PostBind(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) {
} }
func (pl *TestPlugin) Unreserve(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) {
}
func (pl *TestPlugin) Permit(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) (*v1alpha1.Status, time.Duration) { func (pl *TestPlugin) Permit(ctx context.Context, state *v1alpha1.CycleState, p *v1.Pod, nodeName string) (*v1alpha1.Status, time.Duration) {
return v1alpha1.NewStatus(v1alpha1.Code(pl.inj.PermitStatus), "injected status"), time.Duration(0) return v1alpha1.NewStatus(v1alpha1.Code(pl.inj.PermitStatus), "injected status"), time.Duration(0)
} }
@ -1322,7 +1322,7 @@ func TestReservePlugins(t *testing.T) {
inj: injectedResult{ReserveStatus: int(v1alpha1.Unschedulable)}, inj: injectedResult{ReserveStatus: int(v1alpha1.Unschedulable)},
}, },
}, },
wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running "TestPlugin" reserve plugin for pod "": injected status`), wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running Reserve in "TestPlugin" reserve plugin for pod "": injected status`),
}, },
{ {
name: "ErrorReservePlugin", name: "ErrorReservePlugin",
@ -1332,7 +1332,7 @@ func TestReservePlugins(t *testing.T) {
inj: injectedResult{ReserveStatus: int(v1alpha1.Error)}, inj: injectedResult{ReserveStatus: int(v1alpha1.Error)},
}, },
}, },
wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running "TestPlugin" reserve plugin for pod "": injected status`), wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running Reserve in "TestPlugin" reserve plugin for pod "": injected status`),
}, },
{ {
name: "UnschedulableReservePlugin", name: "UnschedulableReservePlugin",
@ -1342,7 +1342,7 @@ func TestReservePlugins(t *testing.T) {
inj: injectedResult{ReserveStatus: int(v1alpha1.UnschedulableAndUnresolvable)}, inj: injectedResult{ReserveStatus: int(v1alpha1.UnschedulableAndUnresolvable)},
}, },
}, },
wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running "TestPlugin" reserve plugin for pod "": injected status`), wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running Reserve in "TestPlugin" reserve plugin for pod "": injected status`),
}, },
{ {
name: "SuccessSuccessReservePlugins", name: "SuccessSuccessReservePlugins",
@ -1370,7 +1370,7 @@ func TestReservePlugins(t *testing.T) {
inj: injectedResult{ReserveStatus: int(v1alpha1.Error)}, inj: injectedResult{ReserveStatus: int(v1alpha1.Error)},
}, },
}, },
wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running "TestPlugin" reserve plugin for pod "": injected status`), wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running Reserve in "TestPlugin" reserve plugin for pod "": injected status`),
}, },
{ {
name: "SuccessErrorReservePlugins", name: "SuccessErrorReservePlugins",
@ -1384,7 +1384,7 @@ func TestReservePlugins(t *testing.T) {
inj: injectedResult{ReserveStatus: int(v1alpha1.Error)}, inj: injectedResult{ReserveStatus: int(v1alpha1.Error)},
}, },
}, },
wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running "TestPlugin 1" reserve plugin for pod "": injected status`), wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running Reserve in "TestPlugin 1" reserve plugin for pod "": injected status`),
}, },
{ {
name: "ErrorSuccessReservePlugin", name: "ErrorSuccessReservePlugin",
@ -1398,7 +1398,7 @@ func TestReservePlugins(t *testing.T) {
inj: injectedResult{ReserveStatus: int(v1alpha1.Success)}, inj: injectedResult{ReserveStatus: int(v1alpha1.Success)},
}, },
}, },
wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running "TestPlugin" reserve plugin for pod "": injected status`), wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running Reserve in "TestPlugin" reserve plugin for pod "": injected status`),
}, },
{ {
name: "UnschedulableAndSuccessReservePlugin", name: "UnschedulableAndSuccessReservePlugin",
@ -1412,7 +1412,7 @@ func TestReservePlugins(t *testing.T) {
inj: injectedResult{ReserveStatus: int(v1alpha1.Success)}, inj: injectedResult{ReserveStatus: int(v1alpha1.Success)},
}, },
}, },
wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running "TestPlugin" reserve plugin for pod "": injected status`), wantStatus: v1alpha1.NewStatus(v1alpha1.Error, `error while running Reserve in "TestPlugin" reserve plugin for pod "": injected status`),
}, },
} }
@ -1440,7 +1440,7 @@ func TestReservePlugins(t *testing.T) {
t.Fatalf("fail to create framework: %s", err) t.Fatalf("fail to create framework: %s", err)
} }
status := f.RunReservePlugins(context.TODO(), nil, pod, "") status := f.RunReservePluginsReserve(context.TODO(), nil, pod, "")
if !reflect.DeepEqual(status, tt.wantStatus) { if !reflect.DeepEqual(status, tt.wantStatus) {
t.Errorf("wrong status code. got %v, want %v", status, tt.wantStatus) t.Errorf("wrong status code. got %v, want %v", status, tt.wantStatus)
@ -1602,13 +1602,13 @@ func TestRecordingMetrics(t *testing.T) {
}, },
{ {
name: "Reserve - Success", name: "Reserve - Success",
action: func(f v1alpha1.Framework) { f.RunReservePlugins(context.Background(), state, pod, "") }, action: func(f v1alpha1.Framework) { f.RunReservePluginsReserve(context.Background(), state, pod, "") },
wantExtensionPoint: "Reserve", wantExtensionPoint: "Reserve",
wantStatus: v1alpha1.Success, wantStatus: v1alpha1.Success,
}, },
{ {
name: "Unreserve - Success", name: "Unreserve - Success",
action: func(f v1alpha1.Framework) { f.RunUnreservePlugins(context.Background(), state, pod, "") }, action: func(f v1alpha1.Framework) { f.RunReservePluginsUnreserve(context.Background(), state, pod, "") },
wantExtensionPoint: "Unreserve", wantExtensionPoint: "Unreserve",
wantStatus: v1alpha1.Success, wantStatus: v1alpha1.Success,
}, },
@ -1660,7 +1660,7 @@ func TestRecordingMetrics(t *testing.T) {
}, },
{ {
name: "Reserve - Error", name: "Reserve - Error",
action: func(f v1alpha1.Framework) { f.RunReservePlugins(context.Background(), state, pod, "") }, action: func(f v1alpha1.Framework) { f.RunReservePluginsReserve(context.Background(), state, pod, "") },
inject: injectedResult{ReserveStatus: int(v1alpha1.Error)}, inject: injectedResult{ReserveStatus: int(v1alpha1.Error)},
wantExtensionPoint: "Reserve", wantExtensionPoint: "Reserve",
wantStatus: v1alpha1.Error, wantStatus: v1alpha1.Error,
@ -1718,7 +1718,6 @@ func TestRecordingMetrics(t *testing.T) {
PreBind: pluginSet, PreBind: pluginSet,
Bind: pluginSet, Bind: pluginSet,
PostBind: pluginSet, PostBind: pluginSet,
Unreserve: pluginSet,
} }
recorder := newMetricsRecorder(100, time.Nanosecond) recorder := newMetricsRecorder(100, time.Nanosecond)
f, err := newFrameworkWithQueueSortAndBind(r, plugins, emptyArgs, withMetricsRecorder(recorder), WithProfileName(testProfileName)) f, err := newFrameworkWithQueueSortAndBind(r, plugins, emptyArgs, withMetricsRecorder(recorder), WithProfileName(testProfileName))

View File

@ -324,17 +324,21 @@ type ScorePlugin interface {
ScoreExtensions() ScoreExtensions ScoreExtensions() ScoreExtensions
} }
// ReservePlugin is an interface for Reserve plugins. These plugins are called // ReservePlugin is an interface for plugins with Reserve and Unreserve
// at the reservation point. These are meant to update the state of the plugin. // methods. These are meant to update the state of the plugin. This concept
// This concept used to be called 'assume' in the original scheduler. // used to be called 'assume' in the original scheduler. These plugins should
// These plugins should return only Success or Error in Status.code. However, // return only Success or Error in Status.code. However, the scheduler accepts
// the scheduler accepts other valid codes as well. Anything other than Success // other valid codes as well. Anything other than Success will lead to
// will lead to rejection of the pod. // rejection of the pod.
type ReservePlugin interface { type ReservePlugin interface {
Plugin Plugin
// Reserve is called by the scheduling framework when the scheduler cache is // Reserve is called by the scheduling framework when the scheduler cache is
// updated. // updated.
Reserve(ctx context.Context, state *CycleState, p *v1.Pod, nodeName string) *Status Reserve(ctx context.Context, state *CycleState, p *v1.Pod, nodeName string) *Status
// Unreserve is called by the scheduling framework when a reserved pod was
// rejected, an error occurred during reservation of subsequent plugins, or
// in a later phase. The Unreserve method implementation must be idempotent.
Unreserve(ctx context.Context, state *CycleState, p *v1.Pod, nodeName string)
} }
// PreBindPlugin is an interface that must be implemented by "prebind" plugins. // PreBindPlugin is an interface that must be implemented by "prebind" plugins.
@ -357,17 +361,6 @@ type PostBindPlugin interface {
PostBind(ctx context.Context, state *CycleState, p *v1.Pod, nodeName string) PostBind(ctx context.Context, state *CycleState, p *v1.Pod, nodeName string)
} }
// UnreservePlugin is an interface for Unreserve plugins. This is an informational
// extension point. If a pod was reserved and then rejected in a later phase, then
// un-reserve plugins will be notified. Un-reserve plugins should clean up state
// associated with the reserved Pod.
type UnreservePlugin interface {
Plugin
// Unreserve is called by the scheduling framework when a reserved pod was
// rejected in a later phase.
Unreserve(ctx context.Context, state *CycleState, p *v1.Pod, nodeName string)
}
// PermitPlugin is an interface that must be implemented by "permit" plugins. // PermitPlugin is an interface that must be implemented by "permit" plugins.
// These plugins are called before a pod is bound to a node. // These plugins are called before a pod is bound to a node.
type PermitPlugin interface { type PermitPlugin interface {
@ -452,13 +445,15 @@ type Framework interface {
// RunPostBindPlugins runs the set of configured postbind plugins. // RunPostBindPlugins runs the set of configured postbind plugins.
RunPostBindPlugins(ctx context.Context, state *CycleState, pod *v1.Pod, nodeName string) RunPostBindPlugins(ctx context.Context, state *CycleState, pod *v1.Pod, nodeName string)
// RunReservePlugins runs the set of configured reserve plugins. If any of these // RunReservePluginsReserve runs the Reserve method of the set of
// plugins returns an error, it does not continue running the remaining ones and // configured reserve plugins. If any of these calls returns an error, it
// returns the error. In such case, pod will not be scheduled. // does not continue running the remaining ones and returns the error. In
RunReservePlugins(ctx context.Context, state *CycleState, pod *v1.Pod, nodeName string) *Status // such case, pod will not be scheduled.
RunReservePluginsReserve(ctx context.Context, state *CycleState, pod *v1.Pod, nodeName string) *Status
// RunUnreservePlugins runs the set of configured unreserve plugins. // RunReservePluginsUnreserve runs the Unreserve method of the set of
RunUnreservePlugins(ctx context.Context, state *CycleState, pod *v1.Pod, nodeName string) // configured reserve plugins.
RunReservePluginsUnreserve(ctx context.Context, state *CycleState, pod *v1.Pod, nodeName string)
// RunPermitPlugins runs the set of configured permit plugins. If any of these // 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 // plugins returns a status other than "Success" or "Wait", it does not continue

View File

@ -516,8 +516,8 @@ func (sched *Scheduler) scheduleOne(ctx context.Context) {
assumedPodInfo := podInfo.DeepCopy() assumedPodInfo := podInfo.DeepCopy()
assumedPod := assumedPodInfo.Pod assumedPod := assumedPodInfo.Pod
// Run "reserve" plugins. // Run the Reserve method of reserve plugins.
if sts := prof.RunReservePlugins(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost); !sts.IsSuccess() { if sts := prof.RunReservePluginsReserve(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost); !sts.IsSuccess() {
sched.recordSchedulingFailure(prof, assumedPodInfo, sts.AsError(), SchedulerError, "") sched.recordSchedulingFailure(prof, assumedPodInfo, sts.AsError(), SchedulerError, "")
metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start)) metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start))
return return
@ -534,7 +534,7 @@ func (sched *Scheduler) scheduleOne(ctx context.Context) {
sched.recordSchedulingFailure(prof, assumedPodInfo, err, SchedulerError, "") sched.recordSchedulingFailure(prof, assumedPodInfo, err, SchedulerError, "")
metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start)) metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start))
// trigger un-reserve plugins to clean up state associated with the reserved Pod // trigger un-reserve plugins to clean up state associated with the reserved Pod
prof.RunUnreservePlugins(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost) prof.RunReservePluginsUnreserve(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost)
return return
} }
@ -553,7 +553,7 @@ func (sched *Scheduler) scheduleOne(ctx context.Context) {
klog.Errorf("scheduler cache ForgetPod failed: %v", forgetErr) klog.Errorf("scheduler cache ForgetPod failed: %v", forgetErr)
} }
// One of the plugins returned status different than success or wait. // One of the plugins returned status different than success or wait.
prof.RunUnreservePlugins(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost) prof.RunReservePluginsUnreserve(schedulingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost)
sched.recordSchedulingFailure(prof, assumedPodInfo, runPermitStatus.AsError(), reason, "") sched.recordSchedulingFailure(prof, assumedPodInfo, runPermitStatus.AsError(), reason, "")
return return
} }
@ -579,7 +579,7 @@ func (sched *Scheduler) scheduleOne(ctx context.Context) {
klog.Errorf("scheduler cache ForgetPod failed: %v", forgetErr) klog.Errorf("scheduler cache ForgetPod failed: %v", forgetErr)
} }
// trigger un-reserve plugins to clean up state associated with the reserved Pod // trigger un-reserve plugins to clean up state associated with the reserved Pod
prof.RunUnreservePlugins(bindingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost) prof.RunReservePluginsUnreserve(bindingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost)
sched.recordSchedulingFailure(prof, assumedPodInfo, waitOnPermitStatus.AsError(), reason, "") sched.recordSchedulingFailure(prof, assumedPodInfo, waitOnPermitStatus.AsError(), reason, "")
return return
} }
@ -594,7 +594,7 @@ func (sched *Scheduler) scheduleOne(ctx context.Context) {
klog.Errorf("scheduler cache ForgetPod failed: %v", forgetErr) klog.Errorf("scheduler cache ForgetPod failed: %v", forgetErr)
} }
// trigger un-reserve plugins to clean up state associated with the reserved Pod // trigger un-reserve plugins to clean up state associated with the reserved Pod
prof.RunUnreservePlugins(bindingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost) prof.RunReservePluginsUnreserve(bindingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost)
sched.recordSchedulingFailure(prof, assumedPodInfo, preBindStatus.AsError(), reason, "") sched.recordSchedulingFailure(prof, assumedPodInfo, preBindStatus.AsError(), reason, "")
return return
} }
@ -603,7 +603,7 @@ func (sched *Scheduler) scheduleOne(ctx context.Context) {
if err != nil { if err != nil {
metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start)) metrics.PodScheduleError(prof.Name, metrics.SinceInSeconds(start))
// trigger un-reserve plugins to clean up state associated with the reserved Pod // trigger un-reserve plugins to clean up state associated with the reserved Pod
prof.RunUnreservePlugins(bindingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost) prof.RunReservePluginsUnreserve(bindingCycleCtx, state, assumedPod, scheduleResult.SuggestedHost)
sched.recordSchedulingFailure(prof, assumedPodInfo, fmt.Errorf("Binding rejected: %v", err), SchedulerError, "") sched.recordSchedulingFailure(prof, assumedPodInfo, fmt.Errorf("Binding rejected: %v", err), SchedulerError, "")
} else { } else {
// Calculating nodeResourceString can be heavy. Avoid it if klog verbosity is below 2. // Calculating nodeResourceString can be heavy. Avoid it if klog verbosity is below 2.

View File

@ -826,7 +826,7 @@ func setupTestSchedulerWithVolumeBinding(volumeBinder scheduling.SchedulerVolume
st.RegisterBindPlugin(defaultbinder.Name, defaultbinder.New), st.RegisterBindPlugin(defaultbinder.Name, defaultbinder.New),
st.RegisterPluginAsExtensions(volumebinding.Name, func(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) { st.RegisterPluginAsExtensions(volumebinding.Name, func(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) {
return &volumebinding.VolumeBinding{Binder: volumeBinder}, nil return &volumebinding.VolumeBinding{Binder: volumeBinder}, nil
}, "PreFilter", "Filter", "Reserve", "Unreserve", "PreBind"), }, "PreFilter", "Filter", "Reserve", "PreBind"),
} }
s, bindingChan, errChan := setupTestScheduler(queuedPodStore, scache, informerFactory, broadcaster, fns...) s, bindingChan, errChan := setupTestScheduler(queuedPodStore, scache, informerFactory, broadcaster, fns...)
informerFactory.Start(stop) informerFactory.Start(stop)
@ -919,7 +919,7 @@ func TestSchedulerWithVolumeBinding(t *testing.T) {
}, },
expectAssumeCalled: true, expectAssumeCalled: true,
eventReason: "FailedScheduling", eventReason: "FailedScheduling",
expectError: fmt.Errorf("error while running %q reserve plugin for pod %q: %v", volumebinding.Name, "foo", assumeErr), expectError: fmt.Errorf("error while running Reserve in %q reserve plugin for pod %q: %v", volumebinding.Name, "foo", assumeErr),
}, },
{ {
name: "bind error", name: "bind error",

View File

@ -100,8 +100,6 @@ func getPluginSetByExtension(plugins *schedulerapi.Plugins, extension string) *s
return initializeIfNeeded(&plugins.Bind) return initializeIfNeeded(&plugins.Bind)
case "Reserve": case "Reserve":
return initializeIfNeeded(&plugins.Reserve) return initializeIfNeeded(&plugins.Reserve)
case "Unreserve":
return initializeIfNeeded(&plugins.Unreserve)
case "Permit": case "Permit":
return initializeIfNeeded(&plugins.Permit) return initializeIfNeeded(&plugins.Permit)
case "PreBind": case "PreBind":

View File

@ -175,7 +175,8 @@ type Plugins struct {
// Score is a list of plugins that should be invoked when ranking nodes that have passed the filtering phase. // Score is a list of plugins that should be invoked when ranking nodes that have passed the filtering phase.
Score *PluginSet `json:"score,omitempty"` Score *PluginSet `json:"score,omitempty"`
// Reserve is a list of plugins invoked when reserving a node to run the pod. // Reserve is a list of plugins invoked when reserving/unreserving resources
// after a node is assigned to run the pod.
Reserve *PluginSet `json:"reserve,omitempty"` Reserve *PluginSet `json:"reserve,omitempty"`
// Permit is a list of plugins that control binding of a Pod. These plugins can prevent or delay binding of a Pod. // Permit is a list of plugins that control binding of a Pod. These plugins can prevent or delay binding of a Pod.
@ -190,9 +191,6 @@ type Plugins struct {
// PostBind is a list of plugins that should be invoked after a pod is successfully bound. // PostBind is a list of plugins that should be invoked after a pod is successfully bound.
PostBind *PluginSet `json:"postBind,omitempty"` PostBind *PluginSet `json:"postBind,omitempty"`
// Unreserve is a list of plugins invoked when a pod that was previously reserved is rejected in a later phase.
Unreserve *PluginSet `json:"unreserve,omitempty"`
} }
// PluginSet specifies enabled and disabled plugins for an extension point. // PluginSet specifies enabled and disabled plugins for an extension point.

View File

@ -449,11 +449,6 @@ func (in *Plugins) DeepCopyInto(out *Plugins) {
*out = new(PluginSet) *out = new(PluginSet)
(*in).DeepCopyInto(*out) (*in).DeepCopyInto(*out)
} }
if in.Unreserve != nil {
in, out := &in.Unreserve, &out.Unreserve
*out = new(PluginSet)
(*in).DeepCopyInto(*out)
}
return return
} }

View File

@ -67,8 +67,11 @@ type PostFilterPlugin struct {
} }
type ReservePlugin struct { type ReservePlugin struct {
name string
numReserveCalled int numReserveCalled int
failReserve bool failReserve bool
numUnreserveCalled int
pluginInvokeEventChan chan pluginInvokeEvent
} }
type PreScorePlugin struct { type PreScorePlugin struct {
@ -96,12 +99,6 @@ type PostBindPlugin struct {
pluginInvokeEventChan chan pluginInvokeEvent pluginInvokeEventChan chan pluginInvokeEvent
} }
type UnreservePlugin struct {
name string
numUnreserveCalled int
pluginInvokeEventChan chan pluginInvokeEvent
}
type PermitPlugin struct { type PermitPlugin struct {
name string name string
numPermitCalled int numPermitCalled int
@ -126,7 +123,6 @@ const (
preScorePluginName = "prescore-plugin" preScorePluginName = "prescore-plugin"
reservePluginName = "reserve-plugin" reservePluginName = "reserve-plugin"
preBindPluginName = "prebind-plugin" preBindPluginName = "prebind-plugin"
unreservePluginName = "unreserve-plugin"
postBindPluginName = "postbind-plugin" postBindPluginName = "postbind-plugin"
permitPluginName = "permit-plugin" permitPluginName = "permit-plugin"
) )
@ -142,7 +138,6 @@ var _ framework.PreScorePlugin = &PreScorePlugin{}
var _ framework.PreBindPlugin = &PreBindPlugin{} var _ framework.PreBindPlugin = &PreBindPlugin{}
var _ framework.BindPlugin = &BindPlugin{} var _ framework.BindPlugin = &BindPlugin{}
var _ framework.PostBindPlugin = &PostBindPlugin{} var _ framework.PostBindPlugin = &PostBindPlugin{}
var _ framework.UnreservePlugin = &UnreservePlugin{}
var _ framework.PermitPlugin = &PermitPlugin{} var _ framework.PermitPlugin = &PermitPlugin{}
// newPlugin returns a plugin factory with specified Plugin. // newPlugin returns a plugin factory with specified Plugin.
@ -247,11 +242,11 @@ func (fp *FilterPlugin) Filter(ctx context.Context, state *framework.CycleState,
// Name returns name of the plugin. // Name returns name of the plugin.
func (rp *ReservePlugin) Name() string { func (rp *ReservePlugin) Name() string {
return reservePluginName return rp.name
} }
// Reserve is a test function that returns an error or nil, depending on the // Reserve is a test function that increments an intenral counter and returns
// value of "failReserve". // an error or nil, depending on the value of "failReserve".
func (rp *ReservePlugin) Reserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status { func (rp *ReservePlugin) Reserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
rp.numReserveCalled++ rp.numReserveCalled++
if rp.failReserve { if rp.failReserve {
@ -260,9 +255,20 @@ func (rp *ReservePlugin) Reserve(ctx context.Context, state *framework.CycleStat
return nil return nil
} }
// reset used to reset reserve plugin. // Unreserve is a test function that increments an internal counter and emits
// an event to a channel. While Unreserve implementations should normally be
// idempotent, we relax that requirement here for testing purposes.
func (rp *ReservePlugin) Unreserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) {
rp.numUnreserveCalled++
if rp.pluginInvokeEventChan != nil {
rp.pluginInvokeEventChan <- pluginInvokeEvent{pluginName: rp.Name(), val: rp.numUnreserveCalled}
}
}
// reset used to reset internal counters.
func (rp *ReservePlugin) reset() { func (rp *ReservePlugin) reset() {
rp.numReserveCalled = 0 rp.numReserveCalled = 0
rp.numUnreserveCalled = 0
} }
// Name returns name of the plugin. // Name returns name of the plugin.
@ -411,25 +417,6 @@ func (pp *PostFilterPlugin) PostFilter(ctx context.Context, state *framework.Cyc
return nil, framework.NewStatus(framework.Success, fmt.Sprintf("make room for pod %v to be schedulable", pod.Name)) return nil, framework.NewStatus(framework.Success, fmt.Sprintf("make room for pod %v to be schedulable", pod.Name))
} }
// Name returns name of the plugin.
func (up *UnreservePlugin) Name() string {
return up.name
}
// Unreserve is a test function that returns an error or nil, depending on the
// value of "failUnreserve".
func (up *UnreservePlugin) Unreserve(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) {
up.numUnreserveCalled++
if up.pluginInvokeEventChan != nil {
up.pluginInvokeEventChan <- pluginInvokeEvent{pluginName: up.Name(), val: up.numUnreserveCalled}
}
}
// reset used to reset numUnreserveCalled.
func (up *UnreservePlugin) reset() {
up.numUnreserveCalled = 0
}
// Name returns name of the plugin. // Name returns name of the plugin.
func (pp *PermitPlugin) Name() string { func (pp *PermitPlugin) Name() string {
return pp.name return pp.name
@ -810,7 +797,7 @@ func TestNormalizeScorePlugin(t *testing.T) {
} }
// TestReservePlugin tests invocation of reserve plugins. // TestReservePlugin tests invocation of reserve plugins.
func TestReservePlugin(t *testing.T) { func TestReservePluginReserve(t *testing.T) {
// Create a plugin registry for testing. Register only a reserve plugin. // Create a plugin registry for testing. Register only a reserve plugin.
reservePlugin := &ReservePlugin{} reservePlugin := &ReservePlugin{}
registry := frameworkruntime.Registry{reservePluginName: newPlugin(reservePlugin)} registry := frameworkruntime.Registry{reservePluginName: newPlugin(reservePlugin)}
@ -830,7 +817,7 @@ func TestReservePlugin(t *testing.T) {
} }
// Create the master and the scheduler with the test plugin set. // Create the master and the scheduler with the test plugin set.
testCtx := initTestSchedulerForFrameworkTest(t, testutils.InitTestMaster(t, "reserve-plugin", nil), 2, testCtx := initTestSchedulerForFrameworkTest(t, testutils.InitTestMaster(t, "reserve-plugin-reserve", nil), 2,
scheduler.WithProfiles(prof), scheduler.WithProfiles(prof),
scheduler.WithFrameworkOutOfTreeRegistry(registry)) scheduler.WithFrameworkOutOfTreeRegistry(registry))
defer testutils.CleanupTest(t, testCtx) defer testutils.CleanupTest(t, testCtx)
@ -962,26 +949,40 @@ func TestPrebindPlugin(t *testing.T) {
} }
} }
// TestUnreservePlugin tests invocation of un-reserve plugin // TestUnreserveReservePlugin tests invocation of the Unreserve operation in
func TestUnreservePlugin(t *testing.T) { // reserve plugins through failures in execution points such as pre-bind. Also
// TODO: register more plugin which would trigger un-reserve plugin // tests that the order of invocation of Unreserve operation is executed in the
preBindPlugin := &PreBindPlugin{} // reverse order of invocation of the Reserve operation.
unreservePlugin := &UnreservePlugin{name: unreservePluginName} func TestReservePluginUnreserve(t *testing.T) {
registry := frameworkruntime.Registry{ numReservePlugins := 3
unreservePluginName: newPlugin(unreservePlugin), pluginInvokeEventChan := make(chan pluginInvokeEvent, numReservePlugins)
preBindPluginName: newPlugin(preBindPlugin),
preBindPlugin := &PreBindPlugin{
failPreBind: true,
}
var reservePlugins []*ReservePlugin
for i := 0; i < numReservePlugins; i++ {
reservePlugins = append(reservePlugins, &ReservePlugin{
name: fmt.Sprintf("%s-%d", reservePluginName, i),
pluginInvokeEventChan: pluginInvokeEventChan,
})
} }
// Setup initial unreserve and prebind plugin for testing. registry := frameworkruntime.Registry{
// TODO(#92229): test more failure points that would trigger Unreserve in
// reserve plugins than just one pre-bind plugin.
preBindPluginName: newPlugin(preBindPlugin),
}
for _, pl := range reservePlugins {
registry[pl.Name()] = newPlugin(pl)
}
// Setup initial reserve and prebind plugin for testing.
prof := schedulerconfig.KubeSchedulerProfile{ prof := schedulerconfig.KubeSchedulerProfile{
SchedulerName: v1.DefaultSchedulerName, SchedulerName: v1.DefaultSchedulerName,
Plugins: &schedulerconfig.Plugins{ Plugins: &schedulerconfig.Plugins{
Unreserve: &schedulerconfig.PluginSet{ Reserve: &schedulerconfig.PluginSet{
Enabled: []schedulerconfig.Plugin{ // filled by looping over reservePlugins
{
Name: unreservePluginName,
},
},
}, },
PreBind: &schedulerconfig.PluginSet{ PreBind: &schedulerconfig.PluginSet{
Enabled: []schedulerconfig.Plugin{ Enabled: []schedulerconfig.Plugin{
@ -992,9 +993,14 @@ func TestUnreservePlugin(t *testing.T) {
}, },
}, },
} }
for _, pl := range reservePlugins {
prof.Plugins.Reserve.Enabled = append(prof.Plugins.Reserve.Enabled, schedulerconfig.Plugin{
Name: pl.Name(),
})
}
// Create the master and the scheduler with the test plugin set. // Create the master and the scheduler with the test plugin set.
testCtx := initTestSchedulerForFrameworkTest(t, testutils.InitTestMaster(t, "unreserve-plugin", nil), 2, testCtx := initTestSchedulerForFrameworkTest(t, testutils.InitTestMaster(t, "reserve-plugin-unreserve", nil), 2,
scheduler.WithProfiles(prof), scheduler.WithProfiles(prof),
scheduler.WithFrameworkOutOfTreeRegistry(registry)) scheduler.WithFrameworkOutOfTreeRegistry(registry))
defer testutils.CleanupTest(t, testCtx) defer testutils.CleanupTest(t, testCtx)
@ -1004,11 +1010,11 @@ func TestUnreservePlugin(t *testing.T) {
preBindFail bool preBindFail bool
}{ }{
{ {
name: "fail preBind unreserve plugin", name: "fail preBind",
preBindFail: true, preBindFail: true,
}, },
{ {
name: "do not fail preBind unreserve plugin", name: "pass preBind",
preBindFail: false, preBindFail: false,
}, },
} }
@ -1025,22 +1031,34 @@ func TestUnreservePlugin(t *testing.T) {
if test.preBindFail { if test.preBindFail {
if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(testCtx.ClientSet, pod.Namespace, pod.Name)); err != nil { if err = wait.Poll(10*time.Millisecond, 30*time.Second, podSchedulingError(testCtx.ClientSet, pod.Namespace, pod.Name)); err != nil {
t.Errorf("Expected a scheduling error, but didn't get it. error: %v", err) t.Errorf("Expected a scheduling error, but didn't get it: %v", err)
}
for i := numReservePlugins - 1; i >= 0; i-- {
select {
case event := <-pluginInvokeEventChan:
expectedPluginName := reservePlugins[i].Name()
if expectedPluginName != event.pluginName {
t.Errorf("event.pluginName = %s, want %s", event.pluginName, expectedPluginName)
}
case <-time.After(time.Second * 30):
t.Errorf("pluginInvokeEventChan receive timed out")
} }
if unreservePlugin.numUnreserveCalled == 0 || unreservePlugin.numUnreserveCalled != preBindPlugin.numPreBindCalled {
t.Errorf("Expected the unreserve plugin to be called %d times, was called %d times.", preBindPlugin.numPreBindCalled, unreservePlugin.numUnreserveCalled)
} }
} else { } else {
if err = testutils.WaitForPodToSchedule(testCtx.ClientSet, pod); err != nil { if err = testutils.WaitForPodToSchedule(testCtx.ClientSet, pod); err != nil {
t.Errorf("Expected the pod to be scheduled. error: %v", err) t.Errorf("Expected the pod to be scheduled, got an error: %v", err)
}
for i, pl := range reservePlugins {
if pl.numUnreserveCalled != 0 {
t.Errorf("reservePlugins[%d].numUnreserveCalled = %d, want 0", i, pl.numUnreserveCalled)
} }
if unreservePlugin.numUnreserveCalled > 0 {
t.Errorf("Didn't expect the unreserve plugin to be called, was called %d times.", unreservePlugin.numUnreserveCalled)
} }
} }
unreservePlugin.reset()
preBindPlugin.reset() preBindPlugin.reset()
for _, pl := range reservePlugins {
pl.reset()
}
testutils.CleanupPods(testCtx.ClientSet, t, []*v1.Pod{pod}) testutils.CleanupPods(testCtx.ClientSet, t, []*v1.Pod{pod})
}) })
} }
@ -1056,12 +1074,13 @@ func TestBindPlugin(t *testing.T) {
testContext := testutils.InitTestMaster(t, "bind-plugin", nil) testContext := testutils.InitTestMaster(t, "bind-plugin", nil)
bindPlugin1 := &BindPlugin{PluginName: "bind-plugin-1", client: testContext.ClientSet} bindPlugin1 := &BindPlugin{PluginName: "bind-plugin-1", client: testContext.ClientSet}
bindPlugin2 := &BindPlugin{PluginName: "bind-plugin-2", client: testContext.ClientSet} bindPlugin2 := &BindPlugin{PluginName: "bind-plugin-2", client: testContext.ClientSet}
unreservePlugin := &UnreservePlugin{name: "mock-unreserve-plugin"} reservePlugin := &ReservePlugin{name: "mock-reserve-plugin"}
postBindPlugin := &PostBindPlugin{name: "mock-post-bind-plugin"} postBindPlugin := &PostBindPlugin{name: "mock-post-bind-plugin"}
// Create a plugin registry for testing. Register an unreserve, a bind plugin and a postBind plugin. // Create a plugin registry for testing. Register reserve, bind, and
// postBind plugins.
registry := frameworkruntime.Registry{ registry := frameworkruntime.Registry{
unreservePlugin.Name(): func(_ runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) { reservePlugin.Name(): func(_ runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) {
return unreservePlugin, nil return reservePlugin, nil
}, },
bindPlugin1.Name(): func(_ runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) { bindPlugin1.Name(): func(_ runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) {
return bindPlugin1, nil return bindPlugin1, nil
@ -1078,8 +1097,8 @@ func TestBindPlugin(t *testing.T) {
prof := schedulerconfig.KubeSchedulerProfile{ prof := schedulerconfig.KubeSchedulerProfile{
SchedulerName: v1.DefaultSchedulerName, SchedulerName: v1.DefaultSchedulerName,
Plugins: &schedulerconfig.Plugins{ Plugins: &schedulerconfig.Plugins{
Unreserve: &schedulerconfig.PluginSet{ Reserve: &schedulerconfig.PluginSet{
Enabled: []schedulerconfig.Plugin{{Name: unreservePlugin.Name()}}, Enabled: []schedulerconfig.Plugin{{Name: reservePlugin.Name()}},
}, },
Bind: &schedulerconfig.PluginSet{ Bind: &schedulerconfig.PluginSet{
// Put DefaultBinder last. // Put DefaultBinder last.
@ -1137,7 +1156,7 @@ func TestBindPlugin(t *testing.T) {
{ {
name: "bind plugin fails to bind the pod", name: "bind plugin fails to bind the pod",
bindPluginStatuses: []*framework.Status{framework.NewStatus(framework.Error, "failed to bind"), framework.NewStatus(framework.Success, "")}, bindPluginStatuses: []*framework.Status{framework.NewStatus(framework.Error, "failed to bind"), framework.NewStatus(framework.Success, "")},
expectInvokeEvents: []pluginInvokeEvent{{pluginName: bindPlugin1.Name(), val: 1}, {pluginName: unreservePlugin.Name(), val: 1}, {pluginName: bindPlugin1.Name(), val: 2}, {pluginName: unreservePlugin.Name(), val: 2}}, expectInvokeEvents: []pluginInvokeEvent{{pluginName: bindPlugin1.Name(), val: 1}, {pluginName: reservePlugin.Name(), val: 1}, {pluginName: bindPlugin1.Name(), val: 2}, {pluginName: reservePlugin.Name(), val: 2}},
}, },
} }
@ -1151,7 +1170,7 @@ func TestBindPlugin(t *testing.T) {
bindPlugin1.pluginInvokeEventChan = pluginInvokeEventChan bindPlugin1.pluginInvokeEventChan = pluginInvokeEventChan
bindPlugin2.pluginInvokeEventChan = pluginInvokeEventChan bindPlugin2.pluginInvokeEventChan = pluginInvokeEventChan
unreservePlugin.pluginInvokeEventChan = pluginInvokeEventChan reservePlugin.pluginInvokeEventChan = pluginInvokeEventChan
postBindPlugin.pluginInvokeEventChan = pluginInvokeEventChan postBindPlugin.pluginInvokeEventChan = pluginInvokeEventChan
// Create a best effort pod. // Create a best effort pod.
@ -1194,8 +1213,8 @@ func TestBindPlugin(t *testing.T) {
}); err != nil { }); err != nil {
t.Errorf("Expected the postbind plugin to be called once, was called %d times.", postBindPlugin.numPostBindCalled) t.Errorf("Expected the postbind plugin to be called once, was called %d times.", postBindPlugin.numPostBindCalled)
} }
if unreservePlugin.numUnreserveCalled != 0 { if reservePlugin.numUnreserveCalled != 0 {
t.Errorf("Expected the unreserve plugin not to be called, was called %d times.", unreservePlugin.numUnreserveCalled) t.Errorf("Expected unreserve to not be called, was called %d times.", reservePlugin.numUnreserveCalled)
} }
} else { } else {
// bind plugin fails to bind the pod // bind plugin fails to bind the pod
@ -1223,7 +1242,7 @@ func TestBindPlugin(t *testing.T) {
postBindPlugin.reset() postBindPlugin.reset()
bindPlugin1.reset() bindPlugin1.reset()
bindPlugin2.reset() bindPlugin2.reset()
unreservePlugin.reset() reservePlugin.reset()
testutils.CleanupPods(testCtx.ClientSet, t, []*v1.Pod{pod}) testutils.CleanupPods(testCtx.ClientSet, t, []*v1.Pod{pod})
}) })
} }

View File

@ -145,7 +145,6 @@ func TestSchedulerCreationFromConfigMap(t *testing.T) {
{Name: "TaintToleration", Weight: 1}, {Name: "TaintToleration", Weight: 1},
}, },
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
}, },
@ -239,7 +238,6 @@ kind: Policy
{Name: "TaintToleration", Weight: 1}, {Name: "TaintToleration", Weight: 1},
}, },
"ReservePlugin": {{Name: "VolumeBinding"}}, "ReservePlugin": {{Name: "VolumeBinding"}},
"UnreservePlugin": {{Name: "VolumeBinding"}},
"PreBindPlugin": {{Name: "VolumeBinding"}}, "PreBindPlugin": {{Name: "VolumeBinding"}},
"BindPlugin": {{Name: "DefaultBinder"}}, "BindPlugin": {{Name: "DefaultBinder"}},
}, },