From 606916760b6f91da7046720737d8601eaad52178 Mon Sep 17 00:00:00 2001 From: wanyaoqi <18528551+wanyaoqi@users.noreply.github.com> Date: Wed, 22 Oct 2025 15:04:58 +0800 Subject: [PATCH] fix(region,host,scheduler): add check kvm cpu max on cpu predicate (#23513) --- pkg/apis/compute/host.go | 2 ++ pkg/compute/models/hosts.go | 2 ++ pkg/hostman/hostinfo/hostinfo.go | 2 ++ pkg/scheduler/algorithm/predicates/error.go | 1 + pkg/scheduler/algorithm/predicates/guest/cpu_predicate.go | 7 ++++++- pkg/scheduler/cache/candidate/base.go | 4 ++++ pkg/scheduler/core/types.go | 1 + pkg/scheduler/test/mock/core.go | 4 ++++ 8 files changed, 22 insertions(+), 1 deletion(-) diff --git a/pkg/apis/compute/host.go b/pkg/apis/compute/host.go index fd453503b8..c259df4365 100644 --- a/pkg/apis/compute/host.go +++ b/pkg/apis/compute/host.go @@ -419,6 +419,8 @@ type HostSizeAttributes struct { CpuMicrocode string `json:"cpu_microcode"` // CPU架构 CpuArchitecture string `json:"cpu_architecture"` + // KVM 允许单台虚机最大 vcpu 个数 + KvmCapMaxVcpu *int `json:"kvm_cap_max_vcpu"` // 内存大小(单位MB) MemSize string `json:"mem_size"` diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 986717e1ee..648963ee1c 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -142,6 +142,8 @@ type SHost struct { CpuMicrocode string `width:"64" charset:"ascii" nullable:"true" get:"domain" update:"domain" create:"domain_optional"` // CPU架构 CpuArchitecture string `width:"16" charset:"ascii" nullable:"true" get:"domain" list:"domain" update:"domain" create:"domain_optional"` + // KVM CAP VCPU MAX + KvmCapMaxVcpu int `nullable:"true" get:"domain" list:"domain" update:"domain" create:"domain_optional"` // 内存大小,单位Mb MemSize int `nullable:"true" list:"domain" update:"domain" create:"domain_optional"` diff --git a/pkg/hostman/hostinfo/hostinfo.go b/pkg/hostman/hostinfo/hostinfo.go index 6e666b572a..68e35f3f7d 100644 --- a/pkg/hostman/hostinfo/hostinfo.go +++ b/pkg/hostman/hostinfo/hostinfo.go @@ -1492,6 +1492,8 @@ func (h *SHostInfo) updateOrCreateHost(hostId string) (*api.HostDetails, error) input.CpuDesc = h.Cpu.cpuInfoProc.Model input.CpuMicrocode = h.Cpu.cpuInfoProc.Microcode input.CpuArchitecture = h.Cpu.CpuArchitecture + maxVcpu := int(h.GetKVMMaxCpus()) + input.KvmCapMaxVcpu = &maxVcpu if h.Cpu.cpuInfoProc.Freq > 0 { input.CpuMhz = &h.Cpu.cpuInfoProc.Freq diff --git a/pkg/scheduler/algorithm/predicates/error.go b/pkg/scheduler/algorithm/predicates/error.go index 1188cbc982..d127419393 100644 --- a/pkg/scheduler/algorithm/predicates/error.go +++ b/pkg/scheduler/algorithm/predicates/error.go @@ -44,6 +44,7 @@ const ( ErrBaremetalHasAlreadyBeenOccupied = `baremetal has already been occupied` ErrPrepaidHostOccupied = `prepaid host occupied` ErrHostCpuArchitectureNotMatch = `host cpu architecture not match` + ErrHostKvmVcpuMaxNotEnough = `host kvm vcpu max not enough` ErrUnknown = `unknown error` ) diff --git a/pkg/scheduler/algorithm/predicates/guest/cpu_predicate.go b/pkg/scheduler/algorithm/predicates/guest/cpu_predicate.go index 069d57ae8c..ff683e65ec 100644 --- a/pkg/scheduler/algorithm/predicates/guest/cpu_predicate.go +++ b/pkg/scheduler/algorithm/predicates/guest/cpu_predicate.go @@ -75,8 +75,13 @@ func (f *CPUPredicate) Execute(ctx context.Context, u *core.Unit, c core.Candida return h.GetResult() } - freeCPUCount := getter.FreeCPUCount(useRsvd) reqCPUCount := int64(d.Ncpu) + if getter.KvmCapMaxVcpuCount() > 0 && reqCPUCount > getter.KvmCapMaxVcpuCount() { + h.Exclude2(predicates.ErrHostKvmVcpuMaxNotEnough, getter.KvmCapMaxVcpuCount(), reqCPUCount) + return h.GetResult() + } + + freeCPUCount := getter.FreeCPUCount(useRsvd) if freeCPUCount < reqCPUCount { totalCPUCount := getter.TotalCPUCount(useRsvd) h.AppendInsufficientResourceError(reqCPUCount, totalCPUCount, freeCPUCount) diff --git a/pkg/scheduler/cache/candidate/base.go b/pkg/scheduler/cache/candidate/base.go index a0a8d641ec..5518ca1c2d 100644 --- a/pkg/scheduler/cache/candidate/base.go +++ b/pkg/scheduler/cache/candidate/base.go @@ -96,6 +96,10 @@ func (b baseHostGetter) CPUArch() string { return b.h.CpuArchitecture } +func (b baseHostGetter) KvmCapMaxVcpuCount() int64 { + return int64(b.h.KvmCapMaxVcpu) +} + func (b baseHostGetter) Cloudprovider() *computemodels.SCloudprovider { return b.h.Cloudprovider } diff --git a/pkg/scheduler/core/types.go b/pkg/scheduler/core/types.go index f562da476b..3664681fd6 100644 --- a/pkg/scheduler/core/types.go +++ b/pkg/scheduler/core/types.go @@ -93,6 +93,7 @@ type CandidatePropertyGetter interface { RunningCPUCount() int64 TotalCPUCount(useRsvd bool) int64 FreeCPUCount(useRsvd bool) int64 + KvmCapMaxVcpuCount() int64 RunningMemorySize() int64 TotalMemorySize(useRsvd bool) int64 diff --git a/pkg/scheduler/test/mock/core.go b/pkg/scheduler/test/mock/core.go index 9060fc9edf..a7ebe7e1c2 100644 --- a/pkg/scheduler/test/mock/core.go +++ b/pkg/scheduler/test/mock/core.go @@ -318,6 +318,10 @@ func (m *MockCandidatePropertyGetter) CPUArch() string { return "" } +func (m *MockCandidatePropertyGetter) KvmCapMaxVcpuCount() int64 { + return -1 +} + // Host indicates an expected call of Host func (mr *MockCandidatePropertyGetterMockRecorder) Host() *gomock.Call { mr.mock.ctrl.T.Helper()