| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- // 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 test
- import (
- "context"
- "fmt"
- "github.com/golang/mock/gomock"
- "yunion.io/x/pkg/tristate"
- "yunion.io/x/pkg/util/netutils"
- "yunion.io/x/pkg/util/sets"
- "yunion.io/x/onecloud/pkg/apis/compute"
- computeapi "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/db"
- "yunion.io/x/onecloud/pkg/compute/models"
- pre "yunion.io/x/onecloud/pkg/scheduler/algorithm/predicates"
- _ "yunion.io/x/onecloud/pkg/scheduler/algorithmprovider"
- "yunion.io/x/onecloud/pkg/scheduler/api"
- "yunion.io/x/onecloud/pkg/scheduler/core"
- "yunion.io/x/onecloud/pkg/scheduler/data_manager/sku"
- "yunion.io/x/onecloud/pkg/scheduler/factory"
- schmodels "yunion.io/x/onecloud/pkg/scheduler/models"
- "yunion.io/x/onecloud/pkg/scheduler/test/mock"
- )
- type sPredicateName string
- var (
- HostStatus sPredicateName = "a-GuestHostStatusFilter"
- Hypervisor sPredicateName = "b-GuestHypervisorFilter"
- Migrate sPredicateName = "d-GuestMigrateFilter"
- Domain sPredicateName = "e-GuestDomainFilter"
- Image sPredicateName = "e-GuestImageFilter"
- CPU sPredicateName = "g-GuestCPUFilter"
- Memory sPredicateName = "h-GuestMemoryFilter"
- Storage sPredicateName = "i-GuestStorageFilter"
- //Network sPredicateName = "j-GuestNetworkFilter"
- IsolateDevice sPredicateName = "k-GuestIsolatedDeviceFilter"
- ResourceType sPredicateName = "l-GuestResourceTypeFilter"
- ServerSku sPredicateName = "n-ServerSkuFilter"
- // scheudle tag predicate, need db operator for now
- HostSchedtag sPredicateName = "c-GuestAggregateFilter"
- DiskSchedtag sPredicateName = "m-GuestDiskschedtagFilter"
- NetworkSchedtag sPredicateName = "o-GuestNetschedtagFilter"
- // quota
- Quota sPredicateName = "z-QuotaFilter"
- basePredicateNames = []sPredicateName{
- HostStatus, Hypervisor, Migrate, Domain, Image, CPU, Memory, Storage,
- IsolateDevice, ResourceType, ServerSku,
- }
- )
- var (
- GlobalDoamin = "default"
- GlobalProject = "default"
- GlobalZone = buildZone("default", "Default")
- GlobalCloudregion = buildCloudregion("default", "Default", "")
- GlobalWire = "default"
- GlobaleVPC = "default"
- )
- func buildCandidate(ctrl *gomock.Controller, param sGetterParams) *mock.MockCandidater {
- cn := mock.NewMockCandidater(ctrl)
- getter := buildGetter(ctrl, param)
- cn.EXPECT().Getter().AnyTimes().Return(getter)
- cn.EXPECT().IndexKey().AnyTimes().Return(getter.Id())
- cn.EXPECT().GetResourceType().AnyTimes().Return(getter.ResourceType())
- cn.EXPECT().AllocCpuNumaPin(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil)
- return cn
- }
- type sGetterParams struct {
- HostId string
- HostName string
- IsPublic *bool
- Domain string
- PublicScope string
- Zone *models.SZone
- CloudRegion *models.SCloudregion
- CloudProvider *models.SCloudprovider
- HostType string
- Storages []*api.CandidateStorage
- Networks []*api.CandidateNetwork
- OvnCapable *bool
- Status string
- HostStatus string
- Enabled *bool
- ResourceType string
- TotalCPUCount int64
- FreeCPUCount int64
- TotalMemorySize int64
- FreeMemorySize int64
- FreeStorageSizeAnyType int64
- QuotaKeys *models.SComputeResourceKeys
- FreeGroupCount int
- Skus []string
- }
- func buildGetter(ctrl *gomock.Controller, param sGetterParams) *mock.MockCandidatePropertyGetter {
- cg := mock.NewMockCandidatePropertyGetter(ctrl)
- cg.EXPECT().Id().AnyTimes().Return(param.HostId)
- cg.EXPECT().Name().AnyTimes().Return(param.HostName)
- cg.EXPECT().Zone().AnyTimes().Return(param.Zone)
- if param.IsPublic == nil {
- cg.EXPECT().IsPublic().AnyTimes().Return(true)
- } else {
- cg.EXPECT().IsPublic().AnyTimes().Return(*param.IsPublic)
- }
- if param.Enabled == nil {
- cg.EXPECT().Enabled().AnyTimes().Return(true)
- } else {
- cg.EXPECT().Enabled().AnyTimes().Return(*param.Enabled)
- }
- cg.EXPECT().DomainId().AnyTimes().Return(param.Domain)
- cg.EXPECT().PublicScope().AnyTimes().Return(param.PublicScope)
- cg.EXPECT().Region().AnyTimes().Return(param.CloudRegion)
- cg.EXPECT().Cloudprovider().AnyTimes().Return(param.CloudProvider)
- cg.EXPECT().HostType().AnyTimes().Return(param.HostType)
- cg.EXPECT().Storages().AnyTimes().Return(param.Storages)
- cg.EXPECT().Networks().AnyTimes().Return(param.Networks)
- cg.EXPECT().Sku(gomock.Any()).AnyTimes().DoAndReturn(func(instanceType string) *sku.ServerSku {
- for _, t := range param.Skus {
- if t != instanceType {
- continue
- }
- return &sku.ServerSku{
- Id: fmt.Sprintf("%s-%s", param.Zone.Id, instanceType),
- ZoneId: param.Zone.Id,
- }
- }
- return nil
- })
- if param.OvnCapable == nil {
- cg.EXPECT().OvnCapable().AnyTimes().Return(false)
- } else {
- cg.EXPECT().OvnCapable().AnyTimes().Return(*param.OvnCapable)
- }
- if len(param.Status) == 0 {
- cg.EXPECT().Status().AnyTimes().Return(computeapi.HOST_HEALTH_STATUS_RUNNING)
- } else {
- cg.EXPECT().Status().AnyTimes().Return(param.Status)
- }
- if len(param.HostStatus) == 0 {
- cg.EXPECT().HostStatus().AnyTimes().Return(computeapi.HOST_ONLINE)
- } else {
- cg.EXPECT().HostStatus().AnyTimes().Return(param.HostStatus)
- }
- if len(param.ResourceType) == 0 {
- cg.EXPECT().ResourceType().AnyTimes().Return(computeapi.HostResourceTypeDefault)
- } else {
- cg.EXPECT().ResourceType().AnyTimes().Return(param.ResourceType)
- }
- cg.EXPECT().TotalCPUCount(gomock.Any()).AnyTimes().Return(param.TotalCPUCount)
- cg.EXPECT().FreeCPUCount(gomock.Any()).AnyTimes().Return(param.FreeCPUCount)
- cg.EXPECT().TotalMemorySize(gomock.Any()).AnyTimes().Return(param.TotalMemorySize)
- cg.EXPECT().FreeMemorySize(gomock.Any()).AnyTimes().Return(param.FreeMemorySize)
- cg.EXPECT().GetFreeCpuNuma().AnyTimes().Return(nil)
- cg.EXPECT().GetFreeStorageSizeOfType(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(param.FreeStorageSizeAnyType, int64(0), nil)
- if param.QuotaKeys != nil {
- cg.EXPECT().GetQuotaKeys(gomock.Any()).AnyTimes().Return(param.QuotaKeys)
- }
- cg.EXPECT().GetFreeGroupCount(gomock.Any()).AnyTimes().Return(param.FreeGroupCount, nil)
- cg.EXPECT().GetPendingUsage().AnyTimes().Return(&schmodels.SPendingUsage{
- NetUsage: schmodels.NewResourcePendingUsage(map[string]int{}),
- })
- return cg
- }
- func buildScheduler(ctrl *gomock.Controller, networkNicCount map[string]int, predicates ...sPredicateName) core.Scheduler {
- pres := sets.NewString()
- for _, pre := range predicates {
- pres.Insert(string(pre))
- }
- algorithmProvider, _ := factory.GetAlgorithmProvider(factory.DefaultProvider)
- mockScheduler := mock.NewMockScheduler(ctrl)
- mockScheduler.EXPECT().BeforePredicate().AnyTimes().Return(nil)
- networkNicGetter := mock.NewMockINetworkNicCountGetter(ctrl)
- networkNicGetter.EXPECT().GetTotalNicCount(gomock.AssignableToTypeOf([]string{})).AnyTimes().DoAndReturn(func(netIds []string) (map[string]int, error) {
- return networkNicCount, nil
- })
- mockScheduler.EXPECT().Predicates().AnyTimes().DoAndReturn(func() (map[string]core.FitPredicate, error) {
- ret, err := factory.GetPredicates(pres)
- if err != nil {
- return nil, err
- }
- if networkNicGetter == nil {
- fmt.Printf("networkNicGetter is nil")
- }
- ret["j-GuestNetworkFilter"] = pre.NewNetworkPredicate().WithNetworkCountGetter(networkNicGetter)
- return ret, nil
- })
- mockScheduler.EXPECT().PriorityConfigs().AnyTimes().DoAndReturn(func() ([]core.PriorityConfig, error) {
- return factory.GetPriorityConfigs(algorithmProvider.PriorityKeys)
- })
- return mockScheduler
- }
- func buildZone(id, name string) *models.SZone {
- zone := &models.SZone{}
- zone.Id = id
- zone.Name = name
- zone.Status = "enable"
- return zone
- }
- func buildCloudregion(id, name, provider string) *models.SCloudregion {
- if len(provider) == 0 {
- provider = computeapi.CLOUD_PROVIDER_ONECLOUD
- }
- return &models.SCloudregion{
- SEnabledStatusStandaloneResourceBase: db.SEnabledStatusStandaloneResourceBase{
- SStatusStandaloneResourceBase: db.SStatusStandaloneResourceBase{
- SStandaloneResourceBase: db.SStandaloneResourceBase{
- SStandaloneAnonResourceBase: db.SStandaloneAnonResourceBase{
- Id: id,
- },
- Name: name,
- },
- SStatusResourceBase: db.SStatusResourceBase{
- Status: "inservice",
- },
- },
- SEnabledResourceBase: db.SEnabledResourceBase{
- Enabled: "true",
- },
- },
- Provider: provider,
- }
- }
- func buildStorage(id, name string, capacity int64) *api.CandidateStorage {
- storage := &models.SStorage{}
- storage.Id, storage.Name = id, name
- storage.DomainId = GlobalDoamin
- storage.IsPublic = true
- storage.PublicScope = "system"
- storage.Status = computeapi.STORAGE_ONLINE
- storage.Enabled = "true"
- storage.ZoneId = GlobalZone.GetId()
- storage.Capacity = capacity
- storage.StorageType = computeapi.STORAGE_LOCAL
- storage.MediumType = computeapi.DISK_TYPE_ROTATE
- storage.Cmtbound = 1.0
- storage.IsSysDiskStore = "true"
- return &api.CandidateStorage{
- SStorage: storage,
- }
- }
- func buildNetwork(id, name string, cidr string) *api.CandidateNetwork {
- network := &models.SNetwork{}
- network.Id, network.Name = id, name
- network.Status = computeapi.NETWORK_STATUS_AVAILABLE
- network.DomainId = GlobalDoamin
- network.ProjectId = GlobalProject
- network.WireId = GlobalWire
- network.ServerType = computeapi.NETWORK_TYPE_GUEST
- prefix, err := netutils.NewIPV4Prefix(cidr)
- if err == nil {
- network.GuestIpMask = prefix.MaskLen
- ipRange := prefix.ToIPRange()
- network.GuestIpStart = ipRange.StartIp().String()
- network.GuestIpEnd = ipRange.EndIp().String()
- }
- return &api.CandidateNetwork{
- SNetwork: network,
- VpcId: GlobaleVPC,
- }
- }
- func buildInstanceGroup(id string, granularity int, force bool) *models.SGroup {
- group := &models.SGroup{}
- group.Id = id
- group.Status = "ready"
- group.DomainId = GlobalDoamin
- group.ProjectId = GlobalProject
- group.Granularity = granularity
- group.ForceDispersion = tristate.NewFromBool(force)
- return nil
- }
- func preSchedule(info *api.SchedInfo, candidates []core.Candidater, isForcast bool) (context.Context, *core.Unit, []core.Candidater, core.IResultHelper) {
- resultHelper := core.SResultHelperFunc(core.ResultHelp)
- if isForcast {
- resultHelper = core.SResultHelperFunc(core.ResultHelpForForcast)
- info.Suggestion = true
- info.IsSuggestion = true
- info.SuggestionAll = true
- info.ShowSuggestionDetails = true
- info.SuggestionLimit = 100
- }
- return context.Background(), core.NewScheduleUnit(info, nil), candidates, resultHelper
- }
- func deepCopy(info *api.SchedInfo) *api.SchedInfo {
- serverConfigs := *info.ServerConfigs
- // disks
- disks := make([]*compute.DiskConfig, len(info.Disks))
- for i := range disks {
- disk := *info.Disks[i]
- disks[i] = &disk
- }
- // network
- networks := make([]*compute.NetworkConfig, len(info.Networks))
- for i := range networks {
- network := *info.Networks[i]
- networks[i] = &network
- }
- // baremetal_disk_config
- bareConfigs := make([]*compute.BaremetalDiskConfig, len(info.BaremetalDiskConfigs))
- for i := range bareConfigs {
- bareConfig := *info.BaremetalDiskConfigs[i]
- bareConfigs[i] = &bareConfig
- }
- // instancegroup
- instancegroupIds := make([]string, len(info.InstanceGroupIds))
- for i := range instancegroupIds {
- instancegroupIds[i] = info.InstanceGroupIds[i]
- }
- serverConfigs.Disks = disks
- serverConfigs.Networks = networks
- serverConfigs.BaremetalDiskConfigs = bareConfigs
- serverConfig := info.ServerConfig
- serverConfig.ServerConfigs = &serverConfigs
- scheduInput := *info.ScheduleInput
- scheduInput.ServerConfig = serverConfig
- copyInfo := *info
- copyInfo.ScheduleInput = &scheduInput
- preferCandidates := make([]string, len(info.PreferCandidates))
- for i := range preferCandidates {
- preferCandidates[i] = info.PreferCandidates[i]
- }
- instanceGroupDetail := make(map[string]*models.SGroup, len(info.InstanceGroupsDetail))
- for k, v := range info.InstanceGroupsDetail {
- // v only read
- instanceGroupDetail[k] = v
- }
- copyInfo.PreferCandidates = preferCandidates
- copyInfo.InstanceGroupsDetail = instanceGroupDetail
- return ©Info
- }
|