From eab87ed6dfa186aacf99fb3e73ba6047c379d7ec Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Mon, 15 Apr 2019 15:17:10 +0800 Subject: [PATCH] fix: scheduler forecast backup server not work (#399) --- pkg/apis/scheduler/api.go | 2 - .../predicates/aggregate_predicate.go | 8 ++-- .../predicates/disk_schedtag_predicate.go | 12 +++--- pkg/scheduler/api/sched.go | 10 ++--- pkg/scheduler/core/context.go | 16 +++++++- pkg/scheduler/handler/backup_helper.go | 40 +++++++++++++----- pkg/scheduler/handler/forecast_helper.go | 41 ++++++++++++------- pkg/scheduler/handler/handler.go | 2 +- 8 files changed, 83 insertions(+), 48 deletions(-) diff --git a/pkg/apis/scheduler/api.go b/pkg/apis/scheduler/api.go index 72580af11c..c86aded4af 100644 --- a/pkg/apis/scheduler/api.go +++ b/pkg/apis/scheduler/api.go @@ -91,8 +91,6 @@ type CandidateResource struct { // used by backup schedule BackupCandidate *CandidateResource `json:"backup_candidate"` - IsMaster bool `json:"is_master"` - IsSlave bool `json:"is_slave"` // Error means no candidate found, include reasons Error string `json:"error"` diff --git a/pkg/scheduler/algorithm/predicates/aggregate_predicate.go b/pkg/scheduler/algorithm/predicates/aggregate_predicate.go index 4a647b9bae..d403f24045 100644 --- a/pkg/scheduler/algorithm/predicates/aggregate_predicate.go +++ b/pkg/scheduler/algorithm/predicates/aggregate_predicate.go @@ -51,10 +51,6 @@ func (p *AggregatePredicate) Clone() core.FitPredicate { func (p *AggregatePredicate) PreExecute(u *core.Unit, cs []core.Candidater) (bool, error) { data := u.SchedData() - if !u.ShouldExecuteSchedtagFilter() { - return false, nil - } - allAggs, err := GetAllSchedtags(computemodels.HostManager.KeywordPlural()) if err != nil { return false, err @@ -68,6 +64,10 @@ func (p *AggregatePredicate) PreExecute(u *core.Unit, cs []core.Candidater) (boo func (p *AggregatePredicate) Execute(u *core.Unit, c core.Candidater) (bool, []core.PredicateFailureReason, error) { h := NewPredicateHelper(p, u, c) + if !u.ShouldExecuteSchedtagFilter(c.Getter().Id()) { + return true, nil, nil + } + if errMsg := p.exec(h); len(errMsg) > 0 { h.Exclude(errMsg) } diff --git a/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go b/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go index 270ad636c1..e261501050 100644 --- a/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go +++ b/pkg/scheduler/algorithm/predicates/disk_schedtag_predicate.go @@ -157,13 +157,13 @@ func (w schedtagStorageW) ResourceType() string { return models.StorageManager.KeywordPlural() } -func (p *DiskSchedtagPredicate) check(d *computeapi.DiskConfig, s *api.CandidateStorage, u *core.Unit) (*PredicatedStorage, error) { +func (p *DiskSchedtagPredicate) check(d *computeapi.DiskConfig, s *api.CandidateStorage, u *core.Unit, c core.Candidater) (*PredicatedStorage, error) { allTags, err := GetAllSchedtags(models.StorageManager.KeywordPlural()) if err != nil { return nil, err } tagPredicate := NewSchedtagPredicate(d.Schedtags, allTags) - shouldExec := u.ShouldExecuteSchedtagFilter() + shouldExec := u.ShouldExecuteSchedtagFilter(c.Getter().Id()) ps := newPredicatedStorage(s, nil, nil) if shouldExec { if err := tagPredicate.Check( @@ -180,11 +180,11 @@ func (p *DiskSchedtagPredicate) check(d *computeapi.DiskConfig, s *api.Candidate return ps, nil } -func (p *DiskSchedtagPredicate) checkStorages(d *computeapi.DiskConfig, storages []*api.CandidateStorage, u *core.Unit) ([]*PredicatedStorage, error) { +func (p *DiskSchedtagPredicate) checkStorages(d *computeapi.DiskConfig, storages []*api.CandidateStorage, u *core.Unit, c core.Candidater) ([]*PredicatedStorage, error) { errs := make([]error, 0) ret := make([]*PredicatedStorage, 0) for _, s := range storages { - ps, err := p.check(d, s, u) + ps, err := p.check(d, s, u, c) if err != nil { // append err, storage not suit disk errs = append(errs, err) @@ -226,7 +226,7 @@ func (p *DiskSchedtagPredicate) Execute(u *core.Unit, c core.Candidater) (bool, break } - matchedStorages, err := p.checkStorages(d, fitStorages, u) + matchedStorages, err := p.checkStorages(d, fitStorages, u, c) if err != nil { h.Exclude(err.Error()) } @@ -267,7 +267,7 @@ func (p *DiskSchedtagPredicate) OnSelectEnd(u *core.Unit, c core.Candidater, cou func (p *DiskSchedtagPredicate) allocatedDiskResource(c core.Candidater, disk *computeapi.DiskConfig, storages []*PredicatedStorage) *schedapi.CandidateDisk { storage := p.selectStorage(disk, storages) - log.Debugf("Select storage %s:%s for disk: %s", storage.Id, storage.Name, disk.Index) + log.Debugf("Select %s storage %s:%s for disk: %s", c.Getter().Name(), storage.Id, storage.Name, disk.Index) return &schedapi.CandidateDisk{ Index: disk.Index, StorageId: storage.Id, diff --git a/pkg/scheduler/api/sched.go b/pkg/scheduler/api/sched.go index 60b711e0fb..f0837d3457 100644 --- a/pkg/scheduler/api/sched.go +++ b/pkg/scheduler/api/sched.go @@ -71,10 +71,6 @@ func NewSchedInfo(input *api.ScheduleInput) *SchedInfo { candidates = append(candidates, data.PreferHost) } - //if !data.Backup && data.PreferBaremetal != "" { - //candidates = append(candidates, data.PreferBaremetal) - //} - if data.ResourceType == "" { data.ResourceType = models.HostResourceTypeShared } @@ -208,7 +204,7 @@ type ForecastResult struct { } type SchedForecastResult struct { - CanCreate bool `json:"can_create"` - Filters []*ForecastFilter `json:"filters"` - Results []ForecastResult `json:"results"` + CanCreate bool `json:"can_create"` + Filters []*ForecastFilter `json:"filters"` + Results []*api.CandidateResource `json:"results"` } diff --git a/pkg/scheduler/core/context.go b/pkg/scheduler/core/context.go index 77a6e1c189..6c1bd013c1 100644 --- a/pkg/scheduler/core/context.go +++ b/pkg/scheduler/core/context.go @@ -415,8 +415,20 @@ func (u *Unit) SchedData() *api.SchedInfo { return u.SchedInfo } -func (u *Unit) ShouldExecuteSchedtagFilter() bool { - return len(u.SchedData().Candidates) == 0 +func (u *Unit) ShouldExecuteSchedtagFilter(hostId string) bool { + schedData := u.SchedData() + if !schedData.Backup { + if len(schedData.PreferHost) != 0 { + return false + } + return true + } + for _, preferHost := range []string{schedData.PreferHost, schedData.PreferBackupHost} { + if preferHost == hostId { + return false + } + } + return true } func (u *Unit) IsPublicCloudProvider() bool { diff --git a/pkg/scheduler/handler/backup_helper.go b/pkg/scheduler/handler/backup_helper.go index deeede41c5..333ee4766c 100644 --- a/pkg/scheduler/handler/backup_helper.go +++ b/pkg/scheduler/handler/backup_helper.go @@ -25,22 +25,27 @@ import ( schedman "yunion.io/x/onecloud/pkg/scheduler/manager" ) -func transToBackupSchedResult(result *core.SchedResultItemList, preferMasterHost, preferBackupHost string, count int64) interface{} { +func transToBackupSchedResult(result *core.SchedResultItemList, preferMasterHost, preferBackupHost string, count int64, setDirty bool) *schedapi.ScheduleOutput { // clean each result sched result item's count for _, item := range result.Data { item.Count = 0 } - apiResults := newBackupSchedResult(result, preferMasterHost, preferBackupHost, count) + apiResults := newBackupSchedResult(result, preferMasterHost, preferBackupHost, count, setDirty) return apiResults } -func newBackupSchedResult(result *core.SchedResultItemList, preferMasterHost, preferBackupHost string, count int64) *schedapi.ScheduleOutput { +func newBackupSchedResult( + result *core.SchedResultItemList, + preferMasterHost, preferBackupHost string, + count int64, + setDirty bool, +) *schedapi.ScheduleOutput { ret := new(schedapi.ScheduleOutput) apiResults := make([]*schedapi.CandidateResource, 0) for i := 0; i < int(count); i++ { log.V(10).Debugf("Select backup host from result: %s", result) - target, err := getSchedBackupResult(result, preferMasterHost, preferBackupHost) + target, err := getSchedBackupResult(result, preferMasterHost, preferBackupHost, setDirty) if err != nil { er := &schedapi.CandidateResource{Error: err.Error()} apiResults = append(apiResults, er) @@ -52,18 +57,22 @@ func newBackupSchedResult(result *core.SchedResultItemList, preferMasterHost, pr return ret } -func getSchedBackupResult(result *core.SchedResultItemList, preferMasterHost, preferBackupHost string) (*schedapi.CandidateResource, error) { +func getSchedBackupResult( + result *core.SchedResultItemList, + preferMasterHost, preferBackupHost string, + setDirty bool, +) (*schedapi.CandidateResource, error) { masterHost := selectMasterHost(result.Data, preferMasterHost, preferBackupHost) if masterHost == nil { - return nil, fmt.Errorf("Can't find master host") + return nil, fmt.Errorf("Can't find master host %q", preferMasterHost) } backupHost := selectBackupHost(masterHost.ID, preferBackupHost, result.Data) if backupHost == nil { - return nil, fmt.Errorf("Can't find backup host by master %s", masterHost.ID) + return nil, fmt.Errorf("Can't find backup host %q by master %q", preferBackupHost, masterHost.ID) } - markHostUsed(masterHost) - markHostUsed(backupHost) + markHostUsed(masterHost, setDirty) + markHostUsed(backupHost, setDirty) sort.Sort(sort.Reverse(result)) ret := masterHost.ToCandidateResource() @@ -71,10 +80,12 @@ func getSchedBackupResult(result *core.SchedResultItemList, preferMasterHost, pr return ret, nil } -func markHostUsed(host *core.SchedResultItem) { +func markHostUsed(host *core.SchedResultItem, setDirty bool) { host.Count++ host.Capacity-- - setHostDirty(host) + if setDirty { + setHostDirty(host) + } } // selectMasterID find master host id run VM @@ -84,6 +95,13 @@ func selectMasterHost(result []*core.SchedResultItem, preferMasterHost, preferBa return nil } host := result[0] + if host.ID == preferMasterHost { + if host.Capacity >= 1 { + return host + } else { + return nil + } + } if host.Capacity >= 1 && host.ID != preferBackupHost { if len(preferMasterHost) == 0 { return host diff --git a/pkg/scheduler/handler/forecast_helper.go b/pkg/scheduler/handler/forecast_helper.go index ea1feb7460..a27f966242 100644 --- a/pkg/scheduler/handler/forecast_helper.go +++ b/pkg/scheduler/handler/forecast_helper.go @@ -17,13 +17,15 @@ package handler import ( "fmt" + schedapi "yunion.io/x/onecloud/pkg/apis/scheduler" "yunion.io/x/onecloud/pkg/scheduler/api" "yunion.io/x/onecloud/pkg/scheduler/core" ) func transToSchedForecastResult(result *core.SchedResultItemList) interface{} { unit := result.Unit - reqCount := int64(unit.SchedData().Count) + schedData := unit.SchedData() + reqCount := int64(schedData.Count) var readyCount int64 filters := make([]*api.ForecastFilter, 0) @@ -65,28 +67,37 @@ func transToSchedForecastResult(result *core.SchedResultItemList) interface{} { items := make([]*core.SchedResultItem, 0) for _, item := range result.Data { hostType := item.Candidater.Getter().HostType() - if result.Unit.SchedData().Hypervisor == hostType { + if schedData.Hypervisor == hostType { items = append(items, item) } } - var results []api.ForecastResult for _, item := range items { addInfos(result.Unit.LogManager.FailedLogs(), item) } - for _, item := range items { - if item.Count <= 0 { - continue - } - readyCount += item.Count - ret := api.ForecastResult{ - Candidate: logIndex(item), - Count: item.Count, - Capacity: item.Capacity, - } - results = append(results, ret) + var output *schedapi.ScheduleOutput + if schedData.Backup { + output = transToBackupSchedResult(result, schedData.PreferHost, schedData.PreferBackupHost, int64(schedData.Count), false) + } else { + output = transToRegionSchedResult(result.Data, int64(schedData.Count)) } + + for _, candi := range output.Candidates { + if len(candi.Error) != 0 { + info, exist := getOrNewFilter("select_candidate") + info.Count++ + msg := candi.Error + info.Messages = append(info.Messages, msg) + if !exist { + filters = append(filters, info) + } + readyCount-- + } else { + readyCount++ + } + } + canCreate := true if readyCount < reqCount { canCreate = false @@ -94,6 +105,6 @@ func transToSchedForecastResult(result *core.SchedResultItemList) interface{} { return &api.SchedForecastResult{ CanCreate: canCreate, Filters: filters, - Results: results, + Results: output.Candidates, } } diff --git a/pkg/scheduler/handler/handler.go b/pkg/scheduler/handler/handler.go index 5d1b564ba8..4433b514f4 100644 --- a/pkg/scheduler/handler/handler.go +++ b/pkg/scheduler/handler/handler.go @@ -290,7 +290,7 @@ func doSyncSchedule(c *gin.Context) { count := int64(schedInfo.Count) var resp interface{} if schedInfo.Backup { - resp = transToBackupSchedResult(result, schedInfo.HostId, schedInfo.PreferBackupHost, count) + resp = transToBackupSchedResult(result, schedInfo.PreferHost, schedInfo.PreferBackupHost, count, true) } else { resp = transToRegionSchedResult(result.Data, count) }