mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
feat: Add IResultHelper
1. Adjust the package structure about pkg/scheduler/core and pkg/scheduler/manager 2. Add IResultHelper 3. Change the signature of genericScheduler.Schedule func (*Unit, []Candidater) (*SchedResultItemList, error) ==> func (*Unit, []Candidater, IResultHelper) (*ScheduleResult, error)
This commit is contained in:
+1
-3
@@ -33,8 +33,6 @@ import (
|
||||
schedmodels "yunion.io/x/onecloud/pkg/scheduler/models"
|
||||
)
|
||||
|
||||
var ErrInstanceGroupNotFound = errors.Error("InstanceGroupNotFound")
|
||||
|
||||
type BaseHostDesc struct {
|
||||
*computemodels.SHost
|
||||
Region *computemodels.SCloudregion `json:"region"`
|
||||
@@ -138,7 +136,7 @@ func (b baseHostGetter) GetFreeGroupCount(groupId string) (int, error) {
|
||||
// Must Be
|
||||
scg, ok := b.h.InstanceGroups[groupId]
|
||||
if !ok {
|
||||
return 0, errors.Wrap(ErrInstanceGroupNotFound, groupId)
|
||||
return 0, errors.Wrap(core.ErrInstanceGroupNotFound, groupId)
|
||||
}
|
||||
free := scg.Granularity - scg.ReferCount
|
||||
if free < 1 {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -29,9 +28,6 @@ import (
|
||||
utiltrace "yunion.io/x/pkg/util/trace"
|
||||
"yunion.io/x/pkg/util/workqueue"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
o "yunion.io/x/onecloud/pkg/scheduler/options"
|
||||
)
|
||||
|
||||
@@ -104,7 +100,7 @@ func NewGenericScheduler(s Scheduler) (*GenericScheduler, error) {
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *GenericScheduler) Schedule(unit *Unit, candidates []Candidater) (*SchedResultItemList, error) {
|
||||
func (g *GenericScheduler) Schedule(unit *Unit, candidates []Candidater, helper IResultHelper) (*ScheduleResult, error) {
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
log.V(4).Infof("Schedule cost time: %v", time.Since(startTime))
|
||||
@@ -171,7 +167,8 @@ func (g *GenericScheduler) Schedule(unit *Unit, candidates []Candidater) (*Sched
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SchedResultItemList{Unit: unit, Data: resultItems}, nil
|
||||
itemList := &SchedResultItemList{Unit: unit, Data: resultItems}
|
||||
return helper.ResultHelp(itemList, unit.SchedInfo), nil
|
||||
}
|
||||
|
||||
func newSchedResultByCtx(u *Unit, count int64, c Candidater) *SchedResultItem {
|
||||
@@ -238,24 +235,6 @@ func generateScheduleResult(u *Unit, scs []*SelectedCandidate, cs []Candidater)
|
||||
return results, nil
|
||||
}
|
||||
|
||||
type SchedResultItem struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Count int64 `json:"count"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Capacity int64 `json:"capacity"`
|
||||
Score Score `json:"score"`
|
||||
|
||||
CapacityDetails map[string]int64 `json:"capacity_details"`
|
||||
ScoreDetails string `json:"score_details"`
|
||||
|
||||
Candidater Candidater `json:"-"`
|
||||
|
||||
*AllocatedResource
|
||||
|
||||
SchedData *api.SchedInfo
|
||||
}
|
||||
|
||||
type StorageUsed struct {
|
||||
used map[string]int64
|
||||
}
|
||||
@@ -285,27 +264,6 @@ func (s *StorageUsed) Add(storageId string, used int64) {
|
||||
}
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) ToCandidateResource(storageUsed *StorageUsed) *schedapi.CandidateResource {
|
||||
return &schedapi.CandidateResource{
|
||||
HostId: item.ID,
|
||||
Name: item.Name,
|
||||
Disks: item.getDisks(storageUsed),
|
||||
Nets: item.Nets,
|
||||
}
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) getDisks(used *StorageUsed) []*schedapi.CandidateDisk {
|
||||
inputs := item.SchedData.Disks
|
||||
ret := make([]*schedapi.CandidateDisk, 0)
|
||||
for idx, disk := range item.Disks {
|
||||
ret = append(ret, &schedapi.CandidateDisk{
|
||||
Index: idx,
|
||||
StorageIds: item.getSortStorageIds(used, inputs[idx], disk.Storages),
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type sortStorage struct {
|
||||
Id string
|
||||
FeeSize int64
|
||||
@@ -335,31 +293,6 @@ func (s sortStorages) getIds() []string {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) getSortStorageIds(
|
||||
used *StorageUsed,
|
||||
disk *compute.DiskConfig,
|
||||
storages []*schedapi.CandidateStorage) []string {
|
||||
reqSize := disk.SizeMb
|
||||
ss := make([]sortStorage, 0)
|
||||
for _, s := range storages {
|
||||
ss = append(ss, sortStorage{
|
||||
Id: s.Id,
|
||||
FeeSize: s.FreeCapacity - used.Get(s.Id),
|
||||
})
|
||||
}
|
||||
toSort := sortStorages(ss)
|
||||
sort.Sort(toSort)
|
||||
sortedStorages := toSort.getIds()
|
||||
ret := make([]string, 0)
|
||||
for idx, id := range sortedStorages {
|
||||
if idx == 0 {
|
||||
used.Add(id, int64(reqSize))
|
||||
}
|
||||
ret = append(ret, id)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetCapacities(u *Unit, id string) (res map[string]int64) {
|
||||
res = make(map[string]int64)
|
||||
capacities := u.GetCapacities(id)
|
||||
@@ -371,51 +304,6 @@ func GetCapacities(u *Unit, id string) (res map[string]int64) {
|
||||
return
|
||||
}
|
||||
|
||||
type SchedResultItems []*SchedResultItem
|
||||
|
||||
func (its SchedResultItems) Len() int {
|
||||
return len(its)
|
||||
}
|
||||
|
||||
func (its SchedResultItems) Swap(i, j int) {
|
||||
its[i], its[j] = its[j], its[i]
|
||||
}
|
||||
|
||||
func (its SchedResultItems) Less(i, j int) bool {
|
||||
it1, it2 := its[i], its[j]
|
||||
return it1.Capacity < it2.Capacity
|
||||
/*
|
||||
ctx := its.Unit
|
||||
|
||||
m := func(c int64) int64 {
|
||||
if c > 0 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
v := func(count, capacity, score int64) int64 {
|
||||
return (m(count) << 42) | (m(capacity) << 21) | score
|
||||
}
|
||||
|
||||
count1, count2 := it1.Count, it2.Count
|
||||
capacity1, capacity2 := ctx.GetCapacity(it1.ID), ctx.GetCapacity(it2.ID)
|
||||
score1, score2 := int64(ctx.GetScore(it1.ID)), int64(ctx.GetScore(it2.ID))
|
||||
|
||||
return v(count1, capacity1, score1) < v(count2, capacity2, score2)
|
||||
*/
|
||||
}
|
||||
|
||||
type SchedResultItemList struct {
|
||||
Unit *Unit
|
||||
Data SchedResultItems
|
||||
}
|
||||
|
||||
func (its SchedResultItemList) String() string {
|
||||
bytes, _ := json.Marshal(its.Data)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
type SelectedCandidate struct {
|
||||
Count int64
|
||||
Candidate Candidater
|
||||
@@ -536,7 +424,11 @@ func findCandidatesThatFit(unit *Unit, candidates []Candidater, predicates map[s
|
||||
unit.AppendFailedCandidates(fcs)
|
||||
}
|
||||
}
|
||||
workqueue.Parallelize(o.GetOptions().PredicateParallelizeSize, len(candidates), checkUnit)
|
||||
workerSize := o.GetOptions().PredicateParallelizeSize
|
||||
if workerSize == 0 {
|
||||
workerSize = 1
|
||||
}
|
||||
workqueue.Parallelize(workerSize, len(candidates), checkUnit)
|
||||
filtered = filtered[:filteredLen]
|
||||
if len(errsChannel) > 0 {
|
||||
errs := make([]error, 0)
|
||||
|
||||
+9
-10
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package manager
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -26,12 +26,10 @@ import (
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/cache/candidate"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core/score"
|
||||
)
|
||||
|
||||
func transToInstanceGroupSchedResult(result *core.SchedResultItemList, schedInfo *api.SchedInfo) *schedapi.ScheduleOutput {
|
||||
func transToInstanceGroupSchedResult(result *SchedResultItemList, schedInfo *api.SchedInfo) *schedapi.ScheduleOutput {
|
||||
for _, item := range result.Data {
|
||||
item.Count = 0
|
||||
}
|
||||
@@ -50,7 +48,7 @@ type sGuestInfo struct {
|
||||
}
|
||||
|
||||
type sSchedResultItem struct {
|
||||
*core.SchedResultItem
|
||||
*SchedResultItem
|
||||
instanceGroupCapacity map[string]int64
|
||||
masterCount int64
|
||||
backupCount int64
|
||||
@@ -69,7 +67,7 @@ func (item *sSchedResultItem) minInstanceGroupCapacity(groupSet map[string]*mode
|
||||
return mincapa
|
||||
}
|
||||
|
||||
func buildHosts(result *core.SchedResultItemList, groups map[string]*models.SGroup) []*sSchedResultItem {
|
||||
func buildHosts(result *SchedResultItemList, groups map[string]*models.SGroup) []*sSchedResultItem {
|
||||
hosts := make([]*sSchedResultItem, result.Data.Len())
|
||||
for i := 0; i < len(result.Data); i++ {
|
||||
getter := result.Data[i].Candidater.Getter()
|
||||
@@ -77,7 +75,7 @@ func buildHosts(result *core.SchedResultItemList, groups map[string]*models.SGro
|
||||
for id, group := range groups {
|
||||
c, err := getter.GetFreeGroupCount(id)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == candidate.ErrInstanceGroupNotFound {
|
||||
if errors.Cause(err) == ErrInstanceGroupNotFound {
|
||||
igCapacity[id] = int64(group.Granularity)
|
||||
} else {
|
||||
igCapacity[id] = 0
|
||||
@@ -124,7 +122,7 @@ func sortHosts(hosts []*sSchedResultItem, guestInfo *sGuestInfo, isBackup *bool)
|
||||
|
||||
// scoreNormalization compare the value of s1 and s2.
|
||||
// If s1 is less than s2, return 1, 0 which means s2 is better than s1.
|
||||
func scoreNormalization(s1, s2 core.Score) (int64, int64) {
|
||||
func scoreNormalization(s1, s2 Score) (int64, int64) {
|
||||
sb1, sb2 := s1.ScoreBucket, s2.ScoreBucket
|
||||
preferLess := score.PreferLess(sb1, sb2)
|
||||
avoidLess := score.AvoidLess(sb1, sb2)
|
||||
@@ -213,7 +211,8 @@ func hostsIndex(hostId string, hosts []*sSchedResultItem) int {
|
||||
// getBackupSchedResult return the ScheduleOutput for guest without backup
|
||||
func getSchedResult(hosts []*sSchedResultItem, guestInfos []sGuestInfo, sid string) *schedapi.ScheduleOutput {
|
||||
apiResults := make([]*schedapi.CandidateResource, 0)
|
||||
storageUsed := core.NewStorageUsed()
|
||||
storageUsed :=
|
||||
NewStorageUsed()
|
||||
var i int = 0
|
||||
for ; i < len(guestInfos); i++ {
|
||||
host := selectHost(hosts, guestInfos[i], nil, true)
|
||||
@@ -244,7 +243,7 @@ func getBackupSchedResult(hosts []*sSchedResultItem, guestInfos, backGuestInfos
|
||||
wireHostMap := buildWireHosts(hosts)
|
||||
apiResults := make([]*schedapi.CandidateResource, 0, len(guestInfos))
|
||||
nowireIds := sets.NewString()
|
||||
storageUsed := core.NewStorageUsed()
|
||||
storageUsed := NewStorageUsed()
|
||||
isBackup := true
|
||||
isMaster := false
|
||||
for i := 0; i < len(guestInfos); i++ {
|
||||
@@ -0,0 +1,122 @@
|
||||
// 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 core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
)
|
||||
|
||||
type ScheduleResult struct {
|
||||
// Result is sync schedule result
|
||||
Result *schedapi.ScheduleOutput
|
||||
// ForecastResult is forecast schedule result
|
||||
ForecastResult interface{}
|
||||
// TestResult is test schedule result
|
||||
TestResult interface{}
|
||||
}
|
||||
|
||||
type SchedResultItem struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Count int64 `json:"count"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Capacity int64 `json:"capacity"`
|
||||
Score Score `json:"score"`
|
||||
|
||||
CapacityDetails map[string]int64 `json:"capacity_details"`
|
||||
ScoreDetails string `json:"score_details"`
|
||||
|
||||
Candidater Candidater `json:"-"`
|
||||
|
||||
*AllocatedResource
|
||||
|
||||
SchedData *api.SchedInfo
|
||||
}
|
||||
|
||||
type SchedResultItemList struct {
|
||||
Unit *Unit
|
||||
Data SchedResultItems
|
||||
}
|
||||
|
||||
func (its SchedResultItemList) String() string {
|
||||
bytes, _ := json.Marshal(its.Data)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
type SchedResultItems []*SchedResultItem
|
||||
|
||||
func (its SchedResultItems) Len() int {
|
||||
return len(its)
|
||||
}
|
||||
|
||||
func (its SchedResultItems) Swap(i, j int) {
|
||||
its[i], its[j] = its[j], its[i]
|
||||
}
|
||||
|
||||
func (its SchedResultItems) Less(i, j int) bool {
|
||||
it1, it2 := its[i], its[j]
|
||||
return it1.Capacity < it2.Capacity
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) ToCandidateResource(storageUsed *StorageUsed) *schedapi.CandidateResource {
|
||||
return &schedapi.CandidateResource{
|
||||
HostId: item.ID,
|
||||
Name: item.Name,
|
||||
Disks: item.getDisks(storageUsed),
|
||||
Nets: item.Nets,
|
||||
}
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) getDisks(used *StorageUsed) []*schedapi.CandidateDisk {
|
||||
inputs := item.SchedData.Disks
|
||||
ret := make([]*schedapi.CandidateDisk, 0)
|
||||
for idx, disk := range item.Disks {
|
||||
ret = append(ret, &schedapi.CandidateDisk{
|
||||
Index: idx,
|
||||
StorageIds: item.getSortStorageIds(used, inputs[idx], disk.Storages),
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) getSortStorageIds(
|
||||
used *StorageUsed,
|
||||
disk *compute.DiskConfig,
|
||||
storages []*schedapi.CandidateStorage) []string {
|
||||
reqSize := disk.SizeMb
|
||||
ss := make([]sortStorage, 0)
|
||||
for _, s := range storages {
|
||||
ss = append(ss, sortStorage{
|
||||
Id: s.Id,
|
||||
FeeSize: s.FreeCapacity - used.Get(s.Id),
|
||||
})
|
||||
}
|
||||
toSort := sortStorages(ss)
|
||||
sort.Sort(toSort)
|
||||
sortedStorages := toSort.getIds()
|
||||
ret := make([]string, 0)
|
||||
for idx, id := range sortedStorages {
|
||||
if idx == 0 {
|
||||
used.Add(id, int64(reqSize))
|
||||
}
|
||||
ret = append(ret, id)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package manager
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -20,13 +20,40 @@ import (
|
||||
"yunion.io/x/log"
|
||||
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
computemodels "yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
schedmodels "yunion.io/x/onecloud/pkg/scheduler/models"
|
||||
)
|
||||
|
||||
func transToSchedResult(result *core.SchedResultItemList, schedInfo *api.SchedInfo) *schedapi.ScheduleOutput {
|
||||
func ResultHelp(result *SchedResultItemList, schedInfo *api.SchedInfo) *ScheduleResult {
|
||||
out := new(ScheduleResult)
|
||||
out.Result = transToSchedResult(result, schedInfo)
|
||||
return out
|
||||
}
|
||||
|
||||
func ResultHelpForForcast(result *SchedResultItemList, _ *api.SchedInfo) *ScheduleResult {
|
||||
out := new(ScheduleResult)
|
||||
out.ForecastResult = transToSchedForecastResult(result)
|
||||
return out
|
||||
}
|
||||
|
||||
func ResultHelpForTest(result *SchedResultItemList, schedInfo *api.SchedInfo) *ScheduleResult {
|
||||
out := new(ScheduleResult)
|
||||
out.TestResult = transToSchedTestResult(result, schedInfo.SuggestionLimit)
|
||||
return out
|
||||
}
|
||||
|
||||
type IResultHelper interface {
|
||||
ResultHelp(result *SchedResultItemList, schedInfo *api.SchedInfo) *ScheduleResult
|
||||
}
|
||||
|
||||
// ResultHelperFunc type is an adapter to allwo the use of ordinary functions as a ResultHelper.
|
||||
// If f is a function with the appropriate signature, ResultHelperFunc(f) is a ResultHelper that calls f.
|
||||
type SResultHelperFunc func(result *SchedResultItemList, schedInfo *api.SchedInfo) *ScheduleResult
|
||||
|
||||
func (r SResultHelperFunc) ResultHelp(result *SchedResultItemList, schedInfo *api.SchedInfo) *ScheduleResult {
|
||||
return r(result, schedInfo)
|
||||
}
|
||||
|
||||
func transToSchedResult(result *SchedResultItemList, schedInfo *api.SchedInfo) *schedapi.ScheduleOutput {
|
||||
if schedInfo.Backup || len(schedInfo.InstanceGroupsDetail) > 0 {
|
||||
return transToInstanceGroupSchedResult(result, schedInfo)
|
||||
} else {
|
||||
@@ -34,24 +61,10 @@ func transToSchedResult(result *core.SchedResultItemList, schedInfo *api.SchedIn
|
||||
}
|
||||
}
|
||||
|
||||
func setSchedPendingUsage(driver computemodels.IGuestDriver, req *api.SchedInfo, resp *schedapi.ScheduleOutput) error {
|
||||
if req.IsSuggestion || IsDriverSkipScheduleDirtyMark(driver) || req.SkipDirtyMarkHost() {
|
||||
return nil
|
||||
}
|
||||
for _, item := range resp.Candidates {
|
||||
schedmodels.HostPendingUsageManager.AddPendingUsage(req, item)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsDriverSkipScheduleDirtyMark(driver computemodels.IGuestDriver) bool {
|
||||
return !(driver.DoScheduleCPUFilter() && driver.DoScheduleMemoryFilter() && driver.DoScheduleStorageFilter())
|
||||
}
|
||||
|
||||
func transToRegionSchedResult(result core.SchedResultItems, count int64, sid string) *schedapi.ScheduleOutput {
|
||||
func transToRegionSchedResult(result SchedResultItems, count int64, sid string) *schedapi.ScheduleOutput {
|
||||
apiResults := make([]*schedapi.CandidateResource, 0)
|
||||
succCount := 0
|
||||
storageUsed := core.NewStorageUsed()
|
||||
storageUsed := NewStorageUsed()
|
||||
for _, nr := range result {
|
||||
for {
|
||||
if nr.Count <= 0 {
|
||||
@@ -79,7 +92,7 @@ func transToRegionSchedResult(result core.SchedResultItems, count int64, sid str
|
||||
}
|
||||
}
|
||||
|
||||
func hostInResultItemsIndex(hostId string, hosts core.SchedResultItems) int {
|
||||
func hostInResultItemsIndex(hostId string, hosts SchedResultItems) int {
|
||||
for i := 0; i < len(hosts); i++ {
|
||||
if hosts[i].ID == hostId {
|
||||
return i
|
||||
@@ -88,7 +101,7 @@ func hostInResultItemsIndex(hostId string, hosts core.SchedResultItems) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
func transToSchedTestResult(result *core.SchedResultItemList, limit int64) interface{} {
|
||||
func transToSchedTestResult(result *SchedResultItemList, limit int64) interface{} {
|
||||
return &api.SchedTestResult{
|
||||
Data: result.Data,
|
||||
Total: int64(result.Data.Len()),
|
||||
@@ -97,7 +110,7 @@ func transToSchedTestResult(result *core.SchedResultItemList, limit int64) inter
|
||||
}
|
||||
}
|
||||
|
||||
func transToSchedForecastResult(result *core.SchedResultItemList) interface{} {
|
||||
func transToSchedForecastResult(result *SchedResultItemList) interface{} {
|
||||
unit := result.Unit
|
||||
schedData := unit.SchedData()
|
||||
reqCount := int64(schedData.Count)
|
||||
@@ -118,13 +131,13 @@ func transToSchedForecastResult(result *core.SchedResultItemList) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
logIndex := func(item *core.SchedResultItem) string {
|
||||
logIndex := func(item *SchedResultItem) string {
|
||||
getter := item.Candidater.Getter()
|
||||
name := getter.Name()
|
||||
id := getter.Id()
|
||||
return fmt.Sprintf("%s:%s", name, id)
|
||||
}
|
||||
addInfos := func(logs core.SchedLogList, item *core.SchedResultItem) {
|
||||
addInfos := func(logs SchedLogList, item *SchedResultItem) {
|
||||
for preName, cnt := range item.CapacityDetails {
|
||||
if cnt > 0 {
|
||||
continue
|
||||
@@ -145,7 +158,7 @@ func transToSchedForecastResult(result *core.SchedResultItemList) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
items := make(core.SchedResultItems, 0)
|
||||
items := make(SchedResultItems, 0)
|
||||
for _, item := range result.Data {
|
||||
hostType := item.Candidater.Getter().HostType()
|
||||
if schedData.Hypervisor == hostType {
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
@@ -34,6 +35,8 @@ const (
|
||||
PriorityStep int = 1
|
||||
)
|
||||
|
||||
var ErrInstanceGroupNotFound = errors.Error("InstanceGroupNotFound")
|
||||
|
||||
type FailedCandidate struct {
|
||||
Stage string
|
||||
Candidate Candidater
|
||||
|
||||
@@ -96,7 +96,7 @@ func (sm *SchedulerManager) start() {
|
||||
}
|
||||
}
|
||||
|
||||
func (sm *SchedulerManager) schedule(info *api.SchedInfo) (*ScheduleResult, error) {
|
||||
func (sm *SchedulerManager) schedule(info *api.SchedInfo) (*core.ScheduleResult, error) {
|
||||
log.V(10).Infof("SchedulerManager do schedule, input: %#v", info)
|
||||
task, err := sm.TaskManager.AddTask(sm, info)
|
||||
if err != nil {
|
||||
@@ -121,7 +121,7 @@ func NewSessionID() string {
|
||||
|
||||
// Schedule process the request data that is scheduled for dispatch and complements
|
||||
// the session information.
|
||||
func Schedule(info *api.SchedInfo) (*ScheduleResult, error) {
|
||||
func Schedule(info *api.SchedInfo) (*core.ScheduleResult, error) {
|
||||
if len(info.SessionId) == 0 {
|
||||
info.SessionId = NewSessionID()
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
computemodels "yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
schedmodels "yunion.io/x/onecloud/pkg/scheduler/models"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -47,7 +49,7 @@ type TaskExecutor struct {
|
||||
callback TaskExecuteCallback
|
||||
unit *core.Unit
|
||||
|
||||
resultItems *ScheduleResult
|
||||
resultItems *core.ScheduleResult
|
||||
resultError error
|
||||
logs []string
|
||||
capacityMap interface{}
|
||||
@@ -81,16 +83,7 @@ func (te *TaskExecutor) Execute() {
|
||||
}
|
||||
}
|
||||
|
||||
type ScheduleResult struct {
|
||||
// Result is sync schedule result
|
||||
Result *schedapi.ScheduleOutput
|
||||
// ForecastResult is forecast schedule result
|
||||
ForecastResult interface{}
|
||||
// TestResult is test schedule result
|
||||
TestResult interface{}
|
||||
}
|
||||
|
||||
func (te *TaskExecutor) execute() (*ScheduleResult, error) {
|
||||
func (te *TaskExecutor) execute() (*core.ScheduleResult, error) {
|
||||
scheduler := te.scheduler
|
||||
genericScheduler, err := core.NewGenericScheduler(scheduler.(core.Scheduler))
|
||||
if err != nil {
|
||||
@@ -105,25 +98,43 @@ func (te *TaskExecutor) execute() (*ScheduleResult, error) {
|
||||
|
||||
te.unit = scheduler.Unit()
|
||||
schedInfo := te.unit.SchedInfo
|
||||
result, err := genericScheduler.Schedule(te.unit, candidates)
|
||||
helper := GenerateResultHelper(schedInfo)
|
||||
result, err := genericScheduler.Schedule(te.unit, candidates, helper)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "genericScheduler.Schedule")
|
||||
}
|
||||
out := new(ScheduleResult)
|
||||
if schedInfo.IsSuggestion {
|
||||
if schedInfo.ShowSuggestionDetails && schedInfo.SuggestionAll {
|
||||
out.ForecastResult = transToSchedForecastResult(result)
|
||||
} else {
|
||||
out.TestResult = transToSchedTestResult(result, schedInfo.SuggestionLimit)
|
||||
}
|
||||
} else {
|
||||
out.Result = transToSchedResult(result, schedInfo)
|
||||
driver := te.unit.GetHypervisorDriver()
|
||||
if err := setSchedPendingUsage(driver, schedInfo, out.Result); err != nil {
|
||||
return nil, errors.Wrap(err, "setSchedPendingUsage")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
return out, nil
|
||||
driver := te.unit.GetHypervisorDriver()
|
||||
if err := setSchedPendingUsage(driver, schedInfo, result.Result); err != nil {
|
||||
return nil, errors.Wrap(err, "setSchedPendingUsage")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GenerateResultHelper(schedInfo *api.SchedInfo) core.IResultHelper {
|
||||
if !schedInfo.IsSuggestion {
|
||||
return core.SResultHelperFunc(core.ResultHelp)
|
||||
}
|
||||
if schedInfo.ShowSuggestionDetails && schedInfo.SuggestionAll {
|
||||
return core.SResultHelperFunc(core.ResultHelpForForcast)
|
||||
}
|
||||
return core.SResultHelperFunc(core.ResultHelpForTest)
|
||||
}
|
||||
|
||||
func setSchedPendingUsage(driver computemodels.IGuestDriver, req *api.SchedInfo, resp *schedapi.ScheduleOutput) error {
|
||||
if req.IsSuggestion || IsDriverSkipScheduleDirtyMark(driver) || req.SkipDirtyMarkHost() {
|
||||
return nil
|
||||
}
|
||||
for _, item := range resp.Candidates {
|
||||
schedmodels.HostPendingUsageManager.AddPendingUsage(req, item)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsDriverSkipScheduleDirtyMark(driver computemodels.IGuestDriver) bool {
|
||||
return !(driver.DoScheduleCPUFilter() && driver.DoScheduleMemoryFilter() && driver.DoScheduleStorageFilter())
|
||||
}
|
||||
|
||||
func (te *TaskExecutor) cleanup() {
|
||||
@@ -138,7 +149,7 @@ func (te *TaskExecutor) Kill() {
|
||||
}
|
||||
}
|
||||
|
||||
func (te *TaskExecutor) GetResult() (*ScheduleResult, error) {
|
||||
func (te *TaskExecutor) GetResult() (*core.ScheduleResult, error) {
|
||||
return te.resultItems, te.resultError
|
||||
}
|
||||
|
||||
@@ -299,7 +310,7 @@ type Task struct {
|
||||
waitCh chan struct{}
|
||||
|
||||
completedCount int
|
||||
resultItems *ScheduleResult
|
||||
resultItems *core.ScheduleResult
|
||||
resultError error
|
||||
}
|
||||
|
||||
@@ -393,12 +404,12 @@ func (t *Task) onCompleted() {
|
||||
close(t.waitCh)
|
||||
}
|
||||
|
||||
func (t *Task) Wait() (*ScheduleResult, error) {
|
||||
func (t *Task) Wait() (*core.ScheduleResult, error) {
|
||||
log.V(10).Infof("Task wait...")
|
||||
<-t.waitCh
|
||||
return t.GetResult()
|
||||
}
|
||||
|
||||
func (t *Task) GetResult() (*ScheduleResult, error) {
|
||||
func (t *Task) GetResult() (*core.ScheduleResult, error) {
|
||||
return t.resultItems, t.resultError
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user