mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 02:37:24 +08:00
fix(scheduler,region,host): guest add alloc extra cpu (#21557)
This commit is contained in:
@@ -474,6 +474,10 @@ type ServerCreateInput struct {
|
||||
// default: 1
|
||||
CpuSockets int `json:"cpu_sockets"`
|
||||
|
||||
// 额外分配 cpu 数量
|
||||
// required: false
|
||||
ExtraCpuCount int `json:"extra_cpu_count"`
|
||||
|
||||
// 用户自定义启动脚本
|
||||
// 支持 #cloud-config yaml 格式及shell脚本
|
||||
// 支持特殊user data平台: Aliyun, Qcloud, Azure, Apsara, Ucloud
|
||||
|
||||
@@ -818,6 +818,8 @@ type ServerChangeConfigInput struct {
|
||||
|
||||
// cpu大小
|
||||
VcpuCount *int `json:"vcpu_count"`
|
||||
// 任务分配CPU大小
|
||||
ExtraCpuCount *int `json:"extra_cpu_count"`
|
||||
// 内存大小, 1024M, 1G
|
||||
VmemSize string `json:"vmem_size"`
|
||||
|
||||
@@ -953,7 +955,8 @@ type SCpuNumaPin struct {
|
||||
SizeMB *int `json:"size_mb"`
|
||||
NodeId int `json:"node_id"`
|
||||
|
||||
VcpuPin []SVCpuPin `json:"vcpu_pin"`
|
||||
VcpuPin []SVCpuPin `json:"vcpu_pin"`
|
||||
ExtraCpuCount int `json:"extra_cpu_count"`
|
||||
}
|
||||
|
||||
type ServerSetBootIndexInput struct {
|
||||
@@ -1309,10 +1312,11 @@ type ServerChangeBandwidthInput struct {
|
||||
}
|
||||
|
||||
type ServerChangeConfigSpecs struct {
|
||||
CpuSockets int `json:"cpu_sockets"`
|
||||
VcpuCount int `json:"vcpu_count"`
|
||||
VmemSize int `json:"vmem_size"`
|
||||
InstanceType string `json:"instance_type"`
|
||||
CpuSockets int `json:"cpu_sockets"`
|
||||
VcpuCount int `json:"vcpu_count"`
|
||||
ExtraCpuCount int `json:"extra_cpu_count"`
|
||||
VmemSize int `json:"vmem_size"`
|
||||
InstanceType string `json:"instance_type"`
|
||||
}
|
||||
|
||||
type DiskResizeSpec struct {
|
||||
@@ -1353,6 +1357,18 @@ func (conf ServerChangeConfigSettings) AddedCpu() int {
|
||||
return addCpu
|
||||
}
|
||||
|
||||
func (conf ServerChangeConfigSettings) ExtraCpuChanged() bool {
|
||||
return conf.ExtraCpuCount != conf.Old.ExtraCpuCount
|
||||
}
|
||||
|
||||
func (conf ServerChangeConfigSettings) AddedExtraCpu() int {
|
||||
addCpu := conf.ExtraCpuCount - conf.Old.ExtraCpuCount
|
||||
if addCpu < 0 {
|
||||
addCpu = 0
|
||||
}
|
||||
return addCpu
|
||||
}
|
||||
|
||||
func (conf ServerChangeConfigSettings) MemChanged() bool {
|
||||
return conf.VmemSize != conf.Old.VmemSize
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ type ScheduleInput struct {
|
||||
OsArch string `json:"os_arch"`
|
||||
ResetCpuNumaPin bool `json:"reset_cpu_numa_pin"`
|
||||
|
||||
// For Migrate
|
||||
ExtraCpuCount int `json:"extra_cpu_count"`
|
||||
CpuNumaPin []SCpuNumaPin `json:"cpu_numa_pin"`
|
||||
PreferNumaNodes []int `json:"prefer_numa_nodes"`
|
||||
|
||||
@@ -199,9 +199,10 @@ type SCpuPin struct {
|
||||
}
|
||||
|
||||
type SCpuNumaPin struct {
|
||||
CpuPin []int
|
||||
NodeId int
|
||||
MemSizeMB *int
|
||||
CpuPin []int
|
||||
NodeId int
|
||||
MemSizeMB *int
|
||||
ExtraCpuCount int
|
||||
}
|
||||
|
||||
type CandidateResource struct {
|
||||
|
||||
@@ -564,6 +564,7 @@ func (base *SBaseGuestDriver) ValidateGuestChangeConfigInput(ctx context.Context
|
||||
confs.Old.VcpuCount = guest.VcpuCount
|
||||
confs.Old.CpuSockets = guest.CpuSockets
|
||||
confs.Old.VmemSize = guest.VmemSize
|
||||
confs.Old.ExtraCpuCount = guest.ExtraCpuCount
|
||||
|
||||
region, err := guest.GetRegion()
|
||||
if err != nil {
|
||||
@@ -586,6 +587,10 @@ func (base *SBaseGuestDriver) ValidateGuestChangeConfigInput(ctx context.Context
|
||||
} else {
|
||||
confs.VcpuCount = guest.VcpuCount
|
||||
}
|
||||
if input.ExtraCpuCount != nil {
|
||||
confs.ExtraCpuCount = *input.ExtraCpuCount
|
||||
}
|
||||
|
||||
if len(input.VmemSize) > 0 {
|
||||
if !regutils.MatchSize(input.VmemSize) {
|
||||
return nil, httperrors.NewBadRequestError("Memory size %q must be number[+unit], like 256M, 1G or 256", input.VmemSize)
|
||||
@@ -678,7 +683,7 @@ func (base *SBaseGuestDriver) ValidateGuestChangeConfigInput(ctx context.Context
|
||||
}
|
||||
|
||||
// schedulr forecast
|
||||
schedDesc := guest.ChangeConfToSchedDesc(confs.AddedCpu(), confs.AddedMem(), schedInputDisks)
|
||||
schedDesc := guest.ChangeConfToSchedDesc(confs.AddedCpu(), confs.AddedExtraCpu(), confs.AddedMem(), schedInputDisks)
|
||||
s := auth.GetAdminSession(ctx, options.Options.Region)
|
||||
canChangeConf, res, err := scheduler.SchedManager.DoScheduleForecast(s, schedDesc, 1)
|
||||
if err != nil {
|
||||
|
||||
@@ -1252,6 +1252,10 @@ func (kvm *SKVMGuestDriver) ValidateGuestChangeConfigInput(ctx context.Context,
|
||||
return nil, errors.Wrap(err, "SBaseGuestDriver.ValidateGuestChangeConfigInput")
|
||||
}
|
||||
|
||||
if confs.ExtraCpuChanged() && guest.Status != api.VM_READY {
|
||||
return nil, httperrors.NewInvalidStatusError("Can't change extra cpus on vm status %s", guest.Status)
|
||||
}
|
||||
|
||||
for i := range input.ResetTrafficLimits {
|
||||
input.ResetTrafficLimits[i].Mac = netutils.FormatMacAddr(input.ResetTrafficLimits[i].Mac)
|
||||
_, err := guest.GetGuestnetworkByMac(input.ResetTrafficLimits[i].Mac)
|
||||
|
||||
@@ -3218,6 +3218,9 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
if added := confs.AddedCpu(); added > 0 {
|
||||
pendingUsage.Cpu = added
|
||||
}
|
||||
if added := confs.AddedExtraCpu(); added > 0 {
|
||||
pendingUsage.Cpu += added
|
||||
}
|
||||
if added := confs.AddedMem(); added > 0 {
|
||||
pendingUsage.Memory = added
|
||||
}
|
||||
@@ -3241,7 +3244,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) ChangeConfToSchedDesc(addCpu, addMem int, schedInputDisks []*api.DiskConfig) *schedapi.ScheduleInput {
|
||||
func (self *SGuest) ChangeConfToSchedDesc(addCpu, addExtraCpu, addMem int, schedInputDisks []*api.DiskConfig) *schedapi.ScheduleInput {
|
||||
region, _ := self.GetRegion()
|
||||
devs, _ := self.GetIsolatedDevices()
|
||||
desc := &schedapi.ScheduleInput{
|
||||
@@ -3260,6 +3263,7 @@ func (self *SGuest) ChangeConfToSchedDesc(addCpu, addMem int, schedInputDisks []
|
||||
OsArch: self.OsArch,
|
||||
ChangeConfig: true,
|
||||
HasIsolatedDevice: len(devs) > 0,
|
||||
ExtraCpuCount: addExtraCpu,
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
@@ -129,6 +129,8 @@ type SGuest struct {
|
||||
VmemSize int `nullable:"false" list:"user" create:"required"`
|
||||
// CPU 内存绑定信息
|
||||
CpuNumaPin jsonutils.JSONObject `nullable:"true" get:"user" update:"user" create:"optional"`
|
||||
// 额外分配的 CPU 数量
|
||||
ExtraCpuCount int `nullable:"false" default:"0" list:"user" create:"optional"`
|
||||
|
||||
// 启动顺序
|
||||
BootOrder string `width:"8" charset:"ascii" nullable:"true" default:"cdn" list:"user" update:"user" create:"optional"`
|
||||
@@ -1324,8 +1326,9 @@ func (guest *SGuest) SetCpuNumaPin(
|
||||
vcpuId := 0
|
||||
for i := range schedCpuNumaPin {
|
||||
cpuNumaPin[i] = api.SCpuNumaPin{
|
||||
SizeMB: schedCpuNumaPin[i].MemSizeMB,
|
||||
NodeId: schedCpuNumaPin[i].NodeId,
|
||||
SizeMB: schedCpuNumaPin[i].MemSizeMB,
|
||||
NodeId: schedCpuNumaPin[i].NodeId,
|
||||
ExtraCpuCount: schedCpuNumaPin[i].ExtraCpuCount,
|
||||
}
|
||||
|
||||
if len(schedCpuNumaPin[i].CpuPin) > 0 {
|
||||
|
||||
@@ -86,6 +86,24 @@ func (task *GuestChangeConfigTask) SaveScheduleResult(ctx context.Context, obj I
|
||||
guest := task.GetObject().(*models.SGuest)
|
||||
task.Params.Set("sched_session_id", jsonutils.NewString(target.SessionId))
|
||||
|
||||
confs, err := task.getChangeConfigSetting()
|
||||
if err != nil {
|
||||
task.markStageFailed(ctx, guest, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
}
|
||||
if confs.ExtraCpuChanged() {
|
||||
_, err = db.Update(guest, func() error {
|
||||
if confs.ExtraCpuCount > 0 {
|
||||
guest.ExtraCpuCount = confs.ExtraCpuCount
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
task.markStageFailed(ctx, guest, jsonutils.NewString(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(target.CpuNumaPin) > 0 {
|
||||
task.Params.Set("cpu_numa_pin", jsonutils.Marshal(target.CpuNumaPin))
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ type SCpuNumaPin struct {
|
||||
Unregular bool
|
||||
NodeId *uint16 `json:",omitempty"`
|
||||
|
||||
VcpuPin []SVCpuPin `json:",omitempty"`
|
||||
VcpuPin []SVCpuPin `json:",omitempty"`
|
||||
ExtraCpuCount int `json:"extra_cpu_count"`
|
||||
}
|
||||
|
||||
type SVCpuPin struct {
|
||||
|
||||
@@ -1459,6 +1459,7 @@ func (s *sPodGuestInstance) createContainer(ctx context.Context, userCred mcclie
|
||||
|
||||
var cpuSetCpus string
|
||||
var cpuSetMems string
|
||||
var extraCpuCount int
|
||||
{
|
||||
cpuSets := sets.NewString()
|
||||
cpuMemSets := sets.NewString()
|
||||
@@ -1470,8 +1471,10 @@ func (s *sPodGuestInstance) createContainer(ctx context.Context, userCred mcclie
|
||||
if cpuNumaPin.NodeId != nil && cpuNumaPin.SizeMB > 0 {
|
||||
cpuMemSets.Insert(fmt.Sprintf("%d", int(*cpuNumaPin.NodeId)))
|
||||
}
|
||||
if cpuNumaPin.ExtraCpuCount > 0 {
|
||||
extraCpuCount += cpuNumaPin.ExtraCpuCount
|
||||
}
|
||||
}
|
||||
|
||||
cpuSetCpus = strings.Join(cpuSets.List(), ",")
|
||||
cpuSetMems = strings.Join(cpuMemSets.List(), ",")
|
||||
} else if len(s.Desc.VcpuPin) > 0 {
|
||||
@@ -1507,7 +1510,7 @@ func (s *sPodGuestInstance) createContainer(ctx context.Context, userCred mcclie
|
||||
Resources: &runtimeapi.LinuxContainerResources{
|
||||
// REF: https://docs.docker.com/config/containers/resource_constraints/#configure-the-default-cfs-scheduler
|
||||
CpuPeriod: s.getDefaultCPUPeriod(),
|
||||
CpuQuota: s.GetDesc().Cpu * s.getDefaultCPUPeriod(),
|
||||
CpuQuota: (s.GetDesc().Cpu + int64(extraCpuCount)) * s.getDefaultCPUPeriod(),
|
||||
//CpuShares: defaultCPUPeriod,
|
||||
MemoryLimitInBytes: s.GetDesc().Mem * 1024 * 1024,
|
||||
OomScoreAdj: 0,
|
||||
|
||||
@@ -454,6 +454,7 @@ type ServerCreateOptionalOptions struct {
|
||||
Iso string `help:"ISO image ID" metavar:"IMAGE_ID" json:"cdrom"`
|
||||
IsoBootIndex *int8 `help:"Iso bootindex" metavar:"IMAGE_BOOT_INDEX" json:"cdrom_boot_index"`
|
||||
VcpuCount int `help:"#CPU cores of VM server, default 1" default:"1" metavar:"<SERVER_CPU_COUNT>" json:"vcpu_count" token:"ncpu"`
|
||||
ExtraCpuCount int `help:"Extra allocate cpu count" json:"extra_cpu_count"`
|
||||
InstanceType string `help:"instance flavor"`
|
||||
Vga string `help:"VGA driver" choices:"std|vmware|cirrus|qxl|virtio"`
|
||||
Vdi string `help:"VDI protocool" choices:"vnc|spice"`
|
||||
@@ -1039,10 +1040,11 @@ func (o *ServerRebuildRootOptions) Description() string {
|
||||
|
||||
type ServerChangeConfigOptions struct {
|
||||
ServerIdOptions
|
||||
VcpuCount *int `help:"New number of Virtual CPU cores" json:"vcpu_count" token:"ncpu"`
|
||||
CpuSockets *int `help:"Cpu sockets"`
|
||||
VmemSize string `help:"New memory size" json:"vmem_size" token:"vmem"`
|
||||
Disk []string `help:"Data disk description, from the 1st data disk to the last one, empty string if no change for this data disk"`
|
||||
VcpuCount *int `help:"New number of Virtual CPU cores" json:"vcpu_count" token:"ncpu"`
|
||||
ExtraCpuCount *int `help:"Extra allocate cpu count" json:"extra_cpu_count"`
|
||||
CpuSockets *int `help:"Cpu sockets"`
|
||||
VmemSize string `help:"New memory size" json:"vmem_size" token:"vmem"`
|
||||
Disk []string `help:"Data disk description, from the 1st data disk to the last one, empty string if no change for this data disk"`
|
||||
|
||||
InstanceType string `help:"Instance Type, e.g. S2.SMALL2 for qcloud"`
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ func (f *CPUPredicate) Execute(ctx context.Context, u *core.Unit, c core.Candida
|
||||
}
|
||||
|
||||
freeCPUCount := getter.FreeCPUCount(useRsvd)
|
||||
reqCPUCount := int64(d.Ncpu)
|
||||
reqCPUCount := int64(d.Ncpu + d.ExtraCpuCount)
|
||||
if freeCPUCount < reqCPUCount {
|
||||
totalCPUCount := getter.TotalCPUCount(useRsvd)
|
||||
h.AppendInsufficientResourceError(reqCPUCount, totalCPUCount, freeCPUCount)
|
||||
|
||||
+10
@@ -1526,6 +1526,11 @@ func (b *HostBuilder) fillGuestsResourceInfo(desc *HostDesc, host *computemodels
|
||||
if err := guest.CpuNumaPin.Unmarshal(&cpuNumaPin); err != nil {
|
||||
return errors.Wrap(err, "unmarshal cpu numa pin")
|
||||
}
|
||||
for i := range cpuNumaPin {
|
||||
if cpuNumaPin[i].ExtraCpuCount > 0 {
|
||||
creatingCPUCount += int64(cpuNumaPin[i].ExtraCpuCount)
|
||||
}
|
||||
}
|
||||
guestsCpuNumaPin = append(guestsCpuNumaPin, cpuNumaPin...)
|
||||
}
|
||||
} else if !IsGuestStoppedStatus(guest) {
|
||||
@@ -1538,6 +1543,11 @@ func (b *HostBuilder) fillGuestsResourceInfo(desc *HostDesc, host *computemodels
|
||||
if err := guest.CpuNumaPin.Unmarshal(&cpuNumaPin); err != nil {
|
||||
return errors.Wrap(err, "unmarshal cpu numa pin")
|
||||
}
|
||||
for i := range cpuNumaPin {
|
||||
if cpuNumaPin[i].ExtraCpuCount > 0 {
|
||||
creatingCPUCount += int64(cpuNumaPin[i].ExtraCpuCount)
|
||||
}
|
||||
}
|
||||
guestsCpuNumaPin = append(guestsCpuNumaPin, cpuNumaPin...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,14 +86,34 @@ func (item *SchedResultItem) ToCandidateResource(storageUsed *StorageUsed) *sche
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) selectCpuNumaPin() []schedapi.SCpuNumaPin {
|
||||
// if !item.Candidater.Getter().Host().EnableNumaAllocate {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
if item.SchedData.LiveMigrate && len(item.SchedData.CpuNumaPin) > 0 {
|
||||
return item.Candidater.AllocCpuNumaPinWithNodeCount(item.SchedData.Ncpu, item.SchedData.Memory, len(item.SchedData.CpuNumaPin))
|
||||
vcpuCount := item.SchedData.Ncpu
|
||||
if item.SchedData.ExtraCpuCount > 0 {
|
||||
vcpuCount += item.SchedData.ExtraCpuCount
|
||||
}
|
||||
return item.Candidater.AllocCpuNumaPin(item.SchedData.Ncpu, item.SchedData.Memory*1024, item.SchedData.PreferNumaNodes)
|
||||
|
||||
var res []schedapi.SCpuNumaPin
|
||||
if item.SchedData.LiveMigrate && len(item.SchedData.CpuNumaPin) > 0 {
|
||||
res = item.Candidater.AllocCpuNumaPinWithNodeCount(vcpuCount, item.SchedData.Memory*1024, len(item.SchedData.CpuNumaPin))
|
||||
} else {
|
||||
res = item.Candidater.AllocCpuNumaPin(vcpuCount, item.SchedData.Memory*1024, item.SchedData.PreferNumaNodes)
|
||||
}
|
||||
|
||||
if item.SchedData.ExtraCpuCount > 0 {
|
||||
extraCpuCnt := item.SchedData.ExtraCpuCount
|
||||
for extraCpuCnt > 0 {
|
||||
cpuMaxIdx := 0
|
||||
cpuMax := -1
|
||||
for i := range res {
|
||||
if len(res[i].CpuPin)-res[i].ExtraCpuCount > cpuMax {
|
||||
cpuMax = len(res[i].CpuPin) - res[i].ExtraCpuCount
|
||||
cpuMaxIdx = i
|
||||
}
|
||||
}
|
||||
res[cpuMaxIdx].ExtraCpuCount += 1
|
||||
extraCpuCnt -= 1
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (item *SchedResultItem) getDisks(used *StorageUsed) []*schedapi.CandidateDisk {
|
||||
|
||||
Reference in New Issue
Block a user