Files
cloudpods/pkg/scheduler/manager/scheduler.go
2020-12-14 14:39:27 +08:00

246 lines
6.6 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package manager
import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
"yunion.io/x/onecloud/pkg/scheduler/data_manager"
"yunion.io/x/onecloud/pkg/scheduler/factory"
)
type CandidatesProvider interface {
ProviderType() string
CandidateType() string
Candidates() ([]core.Candidater, error)
CandidateManager() *data_manager.CandidateManager
}
func candidatesByProvider(provider CandidatesProvider, schedData *api.SchedInfo) ([]core.Candidater, error) {
var hosts []core.Candidater
var err error
candidateManager := provider.CandidateManager()
if len(schedData.PreferCandidates) >= schedData.RequiredCandidates {
hosts, err = candidateManager.GetCandidatesByIds(provider.CandidateType(), schedData.PreferCandidates)
if err != nil {
err = errors.Wrapf(err, "GetCandidatesByIds %v", schedData.PreferCandidates)
}
} else {
args := data_manager.CandidateGetArgs{
ResType: provider.CandidateType(),
ZoneID: schedData.PreferZone,
RegionID: schedData.PreferRegion,
ManagerID: schedData.PreferManager,
HostTypes: schedData.GetCandidateHostTypes(),
}
hosts, err = candidateManager.GetCandidates(args)
if err != nil {
err = errors.Wrapf(err, "GetCandidates by args %s", jsonutils.Marshal(args))
} else if len(hosts) == 0 {
err = errors.Errorf("Scheduler not found candidates by args %s", jsonutils.Marshal(args))
}
}
if err != nil {
return nil, err
}
return hosts, nil
}
type BaseCandidateProvider struct {
scheduler Scheduler
}
func (b *BaseCandidateProvider) CandidateManager() *data_manager.CandidateManager {
return b.scheduler.CandidateManager()
}
type HostCandidatesProvider struct {
*BaseCandidateProvider
}
func NewHostCandidatesProvider(s Scheduler) *HostCandidatesProvider {
return &HostCandidatesProvider{
BaseCandidateProvider: &BaseCandidateProvider{scheduler: s},
}
}
func (h *HostCandidatesProvider) ProviderType() string {
return factory.DefaultProvider
}
func (h *HostCandidatesProvider) CandidateType() string {
return api.HostTypeHost
}
func (h *HostCandidatesProvider) Candidates() ([]core.Candidater, error) {
return candidatesByProvider(h, h.scheduler.SchedData())
}
type BaremetalCandidatesProvider struct {
*BaseCandidateProvider
}
func NewBaremetalCandidatesProvider(s Scheduler) *BaremetalCandidatesProvider {
return &BaremetalCandidatesProvider{
BaseCandidateProvider: &BaseCandidateProvider{scheduler: s},
}
}
func (b *BaremetalCandidatesProvider) ProviderType() string {
return factory.BaremetalProvider
}
func (b *BaremetalCandidatesProvider) CandidateType() string {
return api.SchedTypeBaremetal
}
func (b *BaremetalCandidatesProvider) Candidates() ([]core.Candidater, error) {
return candidatesByProvider(b, b.scheduler.SchedData())
}
type Scheduler interface {
SchedData() *api.SchedInfo
CandidateManager() *data_manager.CandidateManager
// Schedule process
BeforePredicate() error
Predicates() (map[string]core.FitPredicate, error)
PriorityConfigs() ([]core.PriorityConfig, error)
// Schedule input get function
Unit() *core.Unit
Candidates() ([]core.Candidater, error)
//DirtySelectedCandidates([]*core.SelectedCandidate)
}
type BaseScheduler struct {
schedManager *SchedulerManager
schedInfo *api.SchedInfo
}
func newBaseScheduler(manager *SchedulerManager, info *api.SchedInfo) (*BaseScheduler, error) {
s := &BaseScheduler{
schedManager: manager,
schedInfo: info,
}
return s, nil
}
func (s *BaseScheduler) NewSchedUnit() *core.Unit {
return core.NewScheduleUnit(s.schedInfo, s.schedManager)
}
func (s *BaseScheduler) CandidateManager() *data_manager.CandidateManager {
return s.schedManager.CandidateManager
}
func (s *BaseScheduler) SchedData() *api.SchedInfo {
return s.schedInfo
}
func (s *BaseScheduler) Unit() *core.Unit {
return s.NewSchedUnit()
}
func (s *BaseScheduler) BeforePredicate() error {
return nil
}
// GuestScheduler for guest type schedule
type GuestScheduler struct {
*BaseScheduler
algorithmProvider *factory.AlgorithmProviderConfig
candidatesProvider *HostCandidatesProvider
}
func newGuestScheduler(manager *SchedulerManager, info *api.SchedInfo) (*GuestScheduler, error) {
bs, err := newBaseScheduler(manager, info)
if err != nil {
return nil, err
}
algorithmProvider, err := factory.GetAlgorithmProvider(factory.DefaultProvider)
if err != nil {
return nil, err
}
gs := &GuestScheduler{
BaseScheduler: bs,
algorithmProvider: algorithmProvider,
}
candidatesProvider := NewHostCandidatesProvider(gs)
gs.candidatesProvider = candidatesProvider
return gs, nil
}
func (gs *GuestScheduler) Candidates() ([]core.Candidater, error) {
return gs.candidatesProvider.Candidates()
}
func (gs *GuestScheduler) Predicates() (map[string]core.FitPredicate, error) {
return factory.GetPredicates(gs.algorithmProvider.FitPredicateKeys)
}
func (gs *GuestScheduler) PriorityConfigs() ([]core.PriorityConfig, error) {
return factory.GetPriorityConfigs(gs.algorithmProvider.PriorityKeys)
}
// BaremetalScheduler for baremetal type schedule
type BaremetalScheduler struct {
*BaseScheduler
algorithmProvider *factory.AlgorithmProviderConfig
candidatesProvider *BaremetalCandidatesProvider
}
func newBaremetalScheduler(manager *SchedulerManager, info *api.SchedInfo) (*BaremetalScheduler, error) {
bs, err := newBaseScheduler(manager, info)
if err != nil {
return nil, err
}
algorithmProvider, err := factory.GetAlgorithmProvider(factory.BaremetalProvider)
if err != nil {
return nil, err
}
bms := &BaremetalScheduler{
BaseScheduler: bs,
algorithmProvider: algorithmProvider,
}
cp := NewBaremetalCandidatesProvider(bms)
bms.candidatesProvider = cp
return bms, nil
}
func (bs *BaremetalScheduler) Candidates() ([]core.Candidater, error) {
return bs.candidatesProvider.Candidates()
}
func (bs *BaremetalScheduler) Predicates() (map[string]core.FitPredicate, error) {
return factory.GetPredicates(bs.algorithmProvider.FitPredicateKeys)
}
func (bs *BaremetalScheduler) PriorityConfigs() ([]core.PriorityConfig, error) {
return factory.GetPriorityConfigs(bs.algorithmProvider.PriorityKeys)
}