Add NormalizeScore extension point for scheduler framework.
This commit is contained in:
@@ -38,9 +38,14 @@ type PrefilterPlugin struct {
|
||||
}
|
||||
|
||||
type ScorePlugin struct {
|
||||
failScore bool
|
||||
numCalled int
|
||||
highScoreNode string
|
||||
failScore bool
|
||||
numScoreCalled int
|
||||
highScoreNode string
|
||||
}
|
||||
|
||||
type ScoreWithNormalizePlugin struct {
|
||||
numScoreCalled int
|
||||
numNormalizeScoreCalled int
|
||||
}
|
||||
|
||||
type FilterPlugin struct {
|
||||
@@ -91,19 +96,22 @@ type PermitPlugin struct {
|
||||
}
|
||||
|
||||
const (
|
||||
prefilterPluginName = "prefilter-plugin"
|
||||
scorePluginName = "score-plugin"
|
||||
filterPluginName = "filter-plugin"
|
||||
reservePluginName = "reserve-plugin"
|
||||
prebindPluginName = "prebind-plugin"
|
||||
unreservePluginName = "unreserve-plugin"
|
||||
postbindPluginName = "postbind-plugin"
|
||||
permitPluginName = "permit-plugin"
|
||||
prefilterPluginName = "prefilter-plugin"
|
||||
scorePluginName = "score-plugin"
|
||||
scoreWithNormalizePluginName = "score-with-normalize-plugin"
|
||||
filterPluginName = "filter-plugin"
|
||||
reservePluginName = "reserve-plugin"
|
||||
prebindPluginName = "prebind-plugin"
|
||||
unreservePluginName = "unreserve-plugin"
|
||||
postbindPluginName = "postbind-plugin"
|
||||
permitPluginName = "permit-plugin"
|
||||
)
|
||||
|
||||
var _ = framework.PrefilterPlugin(&PrefilterPlugin{})
|
||||
var _ = framework.ScorePlugin(&ScorePlugin{})
|
||||
var _ = framework.FilterPlugin(&FilterPlugin{})
|
||||
var _ = framework.ScorePlugin(&ScorePlugin{})
|
||||
var _ = framework.ScoreWithNormalizePlugin(&ScoreWithNormalizePlugin{})
|
||||
var _ = framework.ReservePlugin(&ReservePlugin{})
|
||||
var _ = framework.PrebindPlugin(&PrebindPlugin{})
|
||||
var _ = framework.BindPlugin(&BindPlugin{})
|
||||
@@ -111,6 +119,13 @@ var _ = framework.PostbindPlugin(&PostbindPlugin{})
|
||||
var _ = framework.UnreservePlugin(&UnreservePlugin{})
|
||||
var _ = framework.PermitPlugin(&PermitPlugin{})
|
||||
|
||||
var scPlugin = &ScorePlugin{}
|
||||
|
||||
// NewScorePlugin is the factory for score plugin.
|
||||
func NewScorePlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
|
||||
return scPlugin, nil
|
||||
}
|
||||
|
||||
// Name returns name of the score plugin.
|
||||
func (sp *ScorePlugin) Name() string {
|
||||
return scorePluginName
|
||||
@@ -119,21 +134,19 @@ func (sp *ScorePlugin) Name() string {
|
||||
// reset returns name of the score plugin.
|
||||
func (sp *ScorePlugin) reset() {
|
||||
sp.failScore = false
|
||||
sp.numCalled = 0
|
||||
sp.numScoreCalled = 0
|
||||
sp.highScoreNode = ""
|
||||
}
|
||||
|
||||
var scPlugin = &ScorePlugin{}
|
||||
|
||||
// Score returns the score of scheduling a pod on a specific node.
|
||||
func (sp *ScorePlugin) Score(pc *framework.PluginContext, p *v1.Pod, nodeName string) (int, *framework.Status) {
|
||||
sp.numCalled++
|
||||
sp.numScoreCalled++
|
||||
if sp.failScore {
|
||||
return 0, framework.NewStatus(framework.Error, fmt.Sprintf("injecting failure for pod %v", p.Name))
|
||||
}
|
||||
|
||||
score := 10
|
||||
if sp.numCalled == 1 {
|
||||
if sp.numScoreCalled == 1 {
|
||||
// The first node is scored the highest, the rest is scored lower.
|
||||
sp.highScoreNode = nodeName
|
||||
score = 100
|
||||
@@ -141,9 +154,34 @@ func (sp *ScorePlugin) Score(pc *framework.PluginContext, p *v1.Pod, nodeName st
|
||||
return score, nil
|
||||
}
|
||||
|
||||
// NewScorePlugin is the factory for score plugin.
|
||||
func NewScorePlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
|
||||
return scPlugin, nil
|
||||
var scoreWithNormalizePlguin = &ScoreWithNormalizePlugin{}
|
||||
|
||||
// Name returns name of the score plugin.
|
||||
func (sp *ScoreWithNormalizePlugin) Name() string {
|
||||
return scoreWithNormalizePluginName
|
||||
}
|
||||
|
||||
// reset returns name of the score plugin.
|
||||
func (sp *ScoreWithNormalizePlugin) reset() {
|
||||
sp.numScoreCalled = 0
|
||||
sp.numNormalizeScoreCalled = 0
|
||||
}
|
||||
|
||||
// Score returns the score of scheduling a pod on a specific node.
|
||||
func (sp *ScoreWithNormalizePlugin) Score(pc *framework.PluginContext, p *v1.Pod, nodeName string) (int, *framework.Status) {
|
||||
sp.numScoreCalled++
|
||||
score := 10
|
||||
return score, nil
|
||||
}
|
||||
|
||||
func (sp *ScoreWithNormalizePlugin) NormalizeScore(pc *framework.PluginContext, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status {
|
||||
sp.numNormalizeScoreCalled++
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewScoreWithNormalizePlugin is the factory for score with normalize plugin.
|
||||
func NewScoreWithNormalizePlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
|
||||
return scoreWithNormalizePlguin, nil
|
||||
}
|
||||
|
||||
var filterPlugin = &FilterPlugin{}
|
||||
@@ -490,9 +528,6 @@ func TestPrefilterPlugin(t *testing.T) {
|
||||
|
||||
// TestScorePlugin tests invocation of score plugins.
|
||||
func TestScorePlugin(t *testing.T) {
|
||||
// Create a plugin registry for testing. Register only a score plugin.
|
||||
registry := framework.Registry{scorePluginName: NewScorePlugin}
|
||||
|
||||
// Setup initial score plugin for testing.
|
||||
plugins := &schedulerconfig.Plugins{
|
||||
Score: &schedulerconfig.PluginSet{
|
||||
@@ -503,22 +538,9 @@ func TestScorePlugin(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
// Set empty plugin config for testing
|
||||
emptyPluginConfig := []schedulerconfig.PluginConfig{}
|
||||
|
||||
// Create the master and the scheduler with the test plugin set.
|
||||
context := initTestSchedulerWithOptions(t,
|
||||
initTestMaster(t, "score-plugin", nil),
|
||||
false, nil, registry, plugins, emptyPluginConfig, false, time.Second)
|
||||
context, cs := initTestContextForScorePlugin(t, plugins)
|
||||
defer cleanupTest(t, context)
|
||||
|
||||
cs := context.clientSet
|
||||
// Add multiple nodes, one of them will be scored much higher than the others.
|
||||
_, err := createNodes(cs, "test-node", nil, 10)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create nodes: %v", err)
|
||||
}
|
||||
|
||||
for i, fail := range []bool{false, true} {
|
||||
scPlugin.failScore = fail
|
||||
// Create a best effort pod.
|
||||
@@ -545,8 +567,8 @@ func TestScorePlugin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
if scPlugin.numCalled == 0 {
|
||||
t.Errorf("Expected the reserve plugin to be called.")
|
||||
if scPlugin.numScoreCalled == 0 {
|
||||
t.Errorf("Expected the score plugin to be called.")
|
||||
}
|
||||
|
||||
scPlugin.reset()
|
||||
@@ -554,6 +576,42 @@ func TestScorePlugin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestNormalizeScorePlugin tests invocation of normalize score plugins.
|
||||
func TestNormalizeScorePlugin(t *testing.T) {
|
||||
// Setup initial score plugin for testing.
|
||||
plugins := &schedulerconfig.Plugins{
|
||||
Score: &schedulerconfig.PluginSet{
|
||||
Enabled: []schedulerconfig.Plugin{
|
||||
{
|
||||
Name: scoreWithNormalizePluginName,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
context, cs := initTestContextForScorePlugin(t, plugins)
|
||||
defer cleanupTest(t, context)
|
||||
|
||||
// Create a best effort pod.
|
||||
pod, err := createPausePod(cs,
|
||||
initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name}))
|
||||
if err != nil {
|
||||
t.Fatalf("Error while creating a test pod: %v", err)
|
||||
}
|
||||
|
||||
if err = waitForPodToSchedule(cs, pod); err != nil {
|
||||
t.Errorf("Expected the pod to be scheduled. error: %v", err)
|
||||
}
|
||||
|
||||
if scoreWithNormalizePlguin.numScoreCalled == 0 {
|
||||
t.Errorf("Expected the score plugin to be called.")
|
||||
}
|
||||
if scoreWithNormalizePlguin.numNormalizeScoreCalled == 0 {
|
||||
t.Error("Expected the normalize score plugin to be called")
|
||||
}
|
||||
|
||||
scoreWithNormalizePlguin.reset()
|
||||
}
|
||||
|
||||
// TestReservePlugin tests invocation of reserve plugins.
|
||||
func TestReservePlugin(t *testing.T) {
|
||||
// Create a plugin registry for testing. Register only a reserve plugin.
|
||||
@@ -1477,3 +1535,26 @@ func TestPreemptWithPermitPlugin(t *testing.T) {
|
||||
perPlugin.reset()
|
||||
cleanupPods(cs, t, []*v1.Pod{waitingPod, preemptorPod})
|
||||
}
|
||||
|
||||
func initTestContextForScorePlugin(t *testing.T, plugins *schedulerconfig.Plugins) (*testContext, *clientset.Clientset) {
|
||||
// Create a plugin registry for testing. Register only a score plugin.
|
||||
registry := framework.Registry{
|
||||
scorePluginName: NewScorePlugin,
|
||||
scoreWithNormalizePluginName: NewScoreWithNormalizePlugin,
|
||||
}
|
||||
|
||||
// Set empty plugin config for testing
|
||||
emptyPluginConfig := []schedulerconfig.PluginConfig{}
|
||||
|
||||
// Create the master and the scheduler with the test plugin set.
|
||||
context := initTestSchedulerWithOptions(t,
|
||||
initTestMaster(t, "score-plugin", nil),
|
||||
false, nil, registry, plugins, emptyPluginConfig, false, time.Second)
|
||||
|
||||
cs := context.clientSet
|
||||
_, err := createNodes(cs, "test-node", nil, 10)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create nodes: %v", err)
|
||||
}
|
||||
return context, cs
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user