89 lines
3.0 KiB
Go
89 lines
3.0 KiB
Go
package runtime
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"k8s.io/klog/v2"
|
|
|
|
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
|
|
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
|
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
|
|
"github.com/karmada-io/karmada/pkg/scheduler/framework"
|
|
plugins2 "github.com/karmada-io/karmada/pkg/scheduler/framework/plugins"
|
|
)
|
|
|
|
// frameworkImpl implements the Framework interface and is responsible for initializing and running scheduler
|
|
// plugins.
|
|
type frameworkImpl struct {
|
|
filterPlugins []framework.FilterPlugin
|
|
scorePlugins []framework.ScorePlugin
|
|
}
|
|
|
|
var _ framework.Framework = &frameworkImpl{}
|
|
|
|
// NewFramework creates a scheduling framework.
|
|
func NewFramework(plugins []string) framework.Framework {
|
|
pluginsMap := plugins2.NewPlugins()
|
|
out := &frameworkImpl{}
|
|
filterPluginsList := reflect.ValueOf(&out.filterPlugins).Elem()
|
|
scorePluginsList := reflect.ValueOf(&out.scorePlugins).Elem()
|
|
|
|
filterType := filterPluginsList.Type().Elem()
|
|
scoreType := scorePluginsList.Type().Elem()
|
|
|
|
for _, p := range plugins {
|
|
plugin := pluginsMap[p]
|
|
if plugin == nil {
|
|
klog.Warningf("scheduling plugin %s not exists", p)
|
|
continue
|
|
}
|
|
addPluginToList(plugin, filterType, &filterPluginsList)
|
|
addPluginToList(plugin, scoreType, &scorePluginsList)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
// RunFilterPlugins runs the set of configured Filter plugins for resources on the cluster.
|
|
// If any of the result is not success, the cluster is not suited for the resource.
|
|
func (frw *frameworkImpl) RunFilterPlugins(ctx context.Context, placement *policyv1alpha1.Placement, resource *workv1alpha1.ObjectReference, cluster *clusterv1alpha1.Cluster) framework.PluginToResult {
|
|
result := make(framework.PluginToResult, len(frw.filterPlugins))
|
|
for _, p := range frw.filterPlugins {
|
|
pluginResult := p.Filter(ctx, placement, resource, cluster)
|
|
result[p.Name()] = pluginResult
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// RunScorePlugins runs the set of configured Filter plugins for resources on the cluster.
|
|
// If any of the result is not success, the cluster is not suited for the resource.
|
|
func (frw *frameworkImpl) RunScorePlugins(ctx context.Context, placement *policyv1alpha1.Placement, clusters []*clusterv1alpha1.Cluster) (framework.PluginToClusterScores, error) {
|
|
result := make(framework.PluginToClusterScores, len(frw.filterPlugins))
|
|
for _, p := range frw.scorePlugins {
|
|
var scoreList framework.ClusterScoreList
|
|
for _, cluster := range clusters {
|
|
score, res := p.Score(ctx, placement, cluster)
|
|
if !res.IsSuccess() {
|
|
return nil, fmt.Errorf("plugin %q failed with: %w", p.Name(), res.AsError())
|
|
}
|
|
scoreList = append(scoreList, framework.ClusterScore{
|
|
Name: cluster.Name,
|
|
Score: score,
|
|
})
|
|
}
|
|
result[p.Name()] = scoreList
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func addPluginToList(plugin framework.Plugin, pluginType reflect.Type, pluginList *reflect.Value) {
|
|
if reflect.TypeOf(plugin).Implements(pluginType) {
|
|
newPlugins := reflect.Append(*pluginList, reflect.ValueOf(plugin))
|
|
pluginList.Set(newPlugins)
|
|
}
|
|
}
|