Files
cloudpods/pkg/scheduler/handler/forecast_helper.go
2020-01-19 10:46:24 +08:00

119 lines
3.0 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 handler
import (
"fmt"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
)
func transToSchedForecastResult(result *core.SchedResultItemList) interface{} {
unit := result.Unit
schedData := unit.SchedData()
reqCount := int64(schedData.Count)
filters := make([]*api.ForecastFilter, 0)
filtersMap := make(map[string]*api.ForecastFilter)
getOrNewFilter := func(preName string) (*api.ForecastFilter, bool) {
if info, ok := filtersMap[preName]; !ok {
i := &api.ForecastFilter{
Filter: preName,
Count: 0,
Messages: make([]string, 0),
}
filtersMap[preName] = i
return i, false
} else {
return info, true
}
}
logIndex := func(item *core.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) {
for preName, cnt := range item.CapacityDetails {
if cnt > 0 {
continue
}
failedLog := logs.Get(logIndex(item))
if failedLog == nil {
log.Errorf("predicate %q count is 0, but not found failed log", preName)
continue
}
for _, msg := range failedLog.Messages {
info, exist := getOrNewFilter(msg.Type)
info.Count++
info.Messages = append(info.Messages, msg.Info)
if !exist {
filters = append(filters, info)
}
}
}
}
items := make(core.SchedResultItems, 0)
for _, item := range result.Data {
hostType := item.Candidater.Getter().HostType()
if schedData.Hypervisor == hostType {
items = append(items, item)
}
}
for _, item := range items {
addInfos(result.Unit.LogManager.FailedLogs(), item)
}
var (
output = transToSchedResult(result, schedData)
readyCount int64
)
for _, candi := range output.Candidates {
if len(candi.Error) != 0 {
info, exist := getOrNewFilter("select_candidate")
msg := candi.Error
info.Messages = append(info.Messages, msg)
if !exist {
filters = append(filters, info)
}
} else {
readyCount++
}
}
canCreate := true
if readyCount < reqCount {
canCreate = false
filters = append(filters, &api.ForecastFilter{
Messages: []string{
fmt.Sprintf("No enough resources: %d/%d(free/request)", readyCount, reqCount),
},
})
}
return &api.SchedForecastResult{
CanCreate: canCreate,
Filters: filters,
Results: output.Candidates,
}
}