diff --git a/pkg/scheduler/api/sched.go b/pkg/scheduler/api/sched.go index 0245b1ce77..07b63d3461 100644 --- a/pkg/scheduler/api/sched.go +++ b/pkg/scheduler/api/sched.go @@ -900,3 +900,14 @@ type SchedTestResult struct { Limit int64 `json:"limit"` Offset int64 `json:"offset"` } + +type ForecastInfo struct { + Filter string `json:"filter"` + Message string `json:"message"` + Count int64 `json:"count"` +} + +type SchedForecastResult struct { + CanCreate bool `json:"can_create"` + Infos []ForecastInfo `json:"infos"` +} diff --git a/pkg/scheduler/handler/forecast_helper.go b/pkg/scheduler/handler/forecast_helper.go new file mode 100644 index 0000000000..874c4efff6 --- /dev/null +++ b/pkg/scheduler/handler/forecast_helper.go @@ -0,0 +1,53 @@ +package handler + +import ( + "yunion.io/x/onecloud/pkg/scheduler/api" + "yunion.io/x/onecloud/pkg/scheduler/core" +) + +func isSelectedHost(item *core.SchedResultItem) { + if item.Count > 0 { + return true + } + return false +} + +func transToSchedForecastResult(result *core.SchedResultItemList) interface{} { + unit := result.Unit + reqCount := unit.SchedData().Count + readyCount := 0 + infos := make([]api.ForecastInfo, 0) + + infoMap := make(map[string]*ForecastInfo) + getOrNewInfo := func(preName string) *ForecastInfo { + if info, ok := infoMap[preName]; !ok { + i := &ForecastInfo{ + Filter: preName, + Count: 1, + } + infoMap[preName] = true + return i + } else { + return info + } + } + addInfos := func(capaDetail map[string]int64) { + for preName, cnt := range capaDetail { + if cnt <= 0 { + getOrNewInfo(preName) + } + } + } + for _, item := range result.Data { + readyCount += item.Count + + } + canCreate := true + if readyCount < reqCount { + canCreate = false + } + return &api.SchedForecastResult{ + CanCreate: false, + Infos: nil, + } +} diff --git a/pkg/scheduler/handler/handler.go b/pkg/scheduler/handler/handler.go index 4cd1ce390c..2d814d6a82 100644 --- a/pkg/scheduler/handler/handler.go +++ b/pkg/scheduler/handler/handler.go @@ -50,6 +50,8 @@ func schedulerActionHandler(c *gin.Context) { switch act { case "test": doSchedulerTest(c) + case "forecast": + doSchedulerForecast(c) case "candidate-list": doCandidateList(c) case "cleanup": @@ -117,6 +119,33 @@ func transToSchedTestResult(result *core.SchedResultItemList, limit int64) inter } } +func doSchedulerForecast(c *gin.Context) { + if !schedman.IsReady() { + c.AbortWithError(http.StatusBadRequest, fmt.Errorf("Global scheduler not init")) + return + } + + sjson, err := simplejson.NewFromReader(c.Request.Body) + if err != nil { + c.AbortWithError(http.StatusBadRequest, err) + return + } + schedInfo, err := api.NewSchedInfo(sjson, true) + if err != nil { + c.AbortWithError(http.StatusBadRequest, err) + return + } + + schedInfo.IsSuggestion = true + schedInfo.ShowSuggestionDetails = true + result, err := schedman.Schedule(schedInfo) + if err != nil { + c.AbortWithError(http.StatusBadRequest, err) + return + } + c.JSON(http.StatusOK, transToSchedForecastResult(result, schedInfo)) +} + func doCandidateList(c *gin.Context) { sjson, err := simplejson.NewFromReader(c.Request.Body) if err != nil {