diff --git a/pkg/compute/guestdrivers/kvm.go b/pkg/compute/guestdrivers/kvm.go index 5c279127ff..4a55a40361 100644 --- a/pkg/compute/guestdrivers/kvm.go +++ b/pkg/compute/guestdrivers/kvm.go @@ -443,9 +443,11 @@ func (self *SKVMGuestDriver) RequestChangeVmConfig(ctx context.Context, guest *m body := jsonutils.NewDict() if vcpuCount > int64(guest.VcpuCount) { body.Set("add_cpu", jsonutils.NewInt(addCpu)) + body.Set("total_cpu", jsonutils.NewInt(int64(guest.VcpuCount))) } if vmemSize > int64(guest.VmemSize) { body.Set("add_mem", jsonutils.NewInt(addMem)) + body.Set("total_mem", jsonutils.NewInt(int64(guest.VmemSize))) } if taskParams.Contains("cpu_numa_pin") { cpuNumaPin, _ := taskParams.Get("cpu_numa_pin") diff --git a/pkg/hostman/guestman/desc/pci.go b/pkg/hostman/guestman/desc/pci.go index 9cd92c9b56..45029e86a0 100644 --- a/pkg/hostman/guestman/desc/pci.go +++ b/pkg/hostman/guestman/desc/pci.go @@ -397,6 +397,13 @@ func NewUsbController(masterbus string, port int) *UsbController { return uc } +func (m *SGuestMem) GuestNumaNodeCount() int { + if m.Mem == nil { + return 0 + } + return len(m.Mem.Mems) + 1 +} + func NewMemDesc(objType, id string, nodeId *uint16, cpus *string) *SMemDesc { md := &SMemDesc{ Object: NewObject(objType, id), diff --git a/pkg/hostman/guestman/guesthandlers/guesthandler.go b/pkg/hostman/guestman/guesthandlers/guesthandler.go index 93517326ad..08b886ff38 100644 --- a/pkg/hostman/guestman/guesthandlers/guesthandler.go +++ b/pkg/hostman/guestman/guesthandlers/guesthandler.go @@ -589,6 +589,14 @@ func guestHotplugCpuMem(ctx context.Context, userCred mcclient.TokenCredential, AddCpuCount: addCpuCount, AddMemSize: addMemSize, } + totalMemSize, err := body.Int("total_mem") + if err == nil { + input.TotalMemSize = &totalMemSize + } + totalCpuCount, err := body.Int("total_cpu") + if err == nil { + input.TotalCpuCount = &totalCpuCount + } if body.Contains("cpu_numa_pin") { cpuNumaPin := make([]schedapi.SCpuNumaPin, 0) diff --git a/pkg/hostman/guestman/guesthelper.go b/pkg/hostman/guestman/guesthelper.go index afb2451cb0..329eeb6e3b 100644 --- a/pkg/hostman/guestman/guesthelper.go +++ b/pkg/hostman/guestman/guesthelper.go @@ -102,6 +102,9 @@ type SGuestHotplugCpuMem struct { AddCpuCount int64 AddMemSize int64 + TotalCpuCount *int64 + TotalMemSize *int64 + CpuNumaPin []*desc.SCpuNumaPin } @@ -275,6 +278,9 @@ func NewGuestCpuSetCounter(info *hostapi.HostTopology, reservedCpus *cpuset.CPUS } func (pq *CpuSetCounter) AllocCpusetWithNodeCount(vcpuCount int, memSizeKB int64, nodeCount int) (map[int]SAllocNumaCpus, error) { + if nodeCount <= 0 { + return nil, nil + } if !pq.NumaEnabled { return pq.AllocCpuset(vcpuCount, memSizeKB, -1) } diff --git a/pkg/hostman/guestman/guestman.go b/pkg/hostman/guestman/guestman.go index 9e632f913f..50defaa135 100644 --- a/pkg/hostman/guestman/guestman.go +++ b/pkg/hostman/guestman/guestman.go @@ -1485,7 +1485,7 @@ func (m *SGuestManager) HotplugCpuMem(ctx context.Context, params interface{}) ( } guest, _ := m.GetServer(hotplugParams.Sid) - NewGuestHotplugCpuMemTask(ctx, guest, int(hotplugParams.AddCpuCount), int(hotplugParams.AddMemSize), hotplugParams.CpuNumaPin).Start() + NewGuestHotplugCpuMemTask(ctx, guest, hotplugParams).Start() return nil, nil } diff --git a/pkg/hostman/guestman/guesttasks.go b/pkg/hostman/guestman/guesttasks.go index af6faaf2cf..407f0449aa 100644 --- a/pkg/hostman/guestman/guesttasks.go +++ b/pkg/hostman/guestman/guesttasks.go @@ -2452,15 +2452,30 @@ type SGuestHotplugCpuMemTask struct { } func NewGuestHotplugCpuMemTask( - ctx context.Context, s *SKVMGuestInstance, addCpuCount, addMemSize int, cpuNumaPin []*desc.SCpuNumaPin, + ctx context.Context, s *SKVMGuestInstance, input *SGuestHotplugCpuMem, ) *SGuestHotplugCpuMemTask { - return &SGuestHotplugCpuMemTask{ + t := &SGuestHotplugCpuMemTask{ SKVMGuestInstance: s, ctx: ctx, - addCpuCount: addCpuCount, - addMemSize: addMemSize, - cpuNumaPin: cpuNumaPin, + addCpuCount: int(input.AddCpuCount), + addMemSize: int(input.AddMemSize), + cpuNumaPin: input.CpuNumaPin, } + if input.TotalCpuCount != nil && input.AddCpuCount > 0 { + if s.Desc.Cpu > *input.TotalCpuCount { + addedCpuCount := int(s.Desc.Cpu - *input.TotalCpuCount) + t.addCpuCount -= addedCpuCount + } + } + log.Infof("guest %s add cpu count %d", s.Id, t.addCpuCount) + if input.TotalMemSize != nil && input.AddMemSize > 0 { + if s.Desc.Mem > *input.TotalMemSize { + addedMemSize := int(s.Desc.Mem - *input.TotalMemSize) + t.addMemSize -= addedMemSize + } + } + log.Infof("guest %s add mem size %d", s.Id, t.addMemSize) + return t } // First at all add cpu count, second add mem size @@ -2586,7 +2601,11 @@ func (task *SGuestHotplugCpuMemTask) startAddMem() { } func (task *SGuestHotplugCpuMemTask) onGetSlotIndex(index int) { - var newIndex = index + len(task.Desc.MemDesc.Mem.Mems) + var newIndex = index + if task.Desc.MemDesc.Mem != nil { + newIndex += len(task.Desc.MemDesc.Mem.Mems) + } + task.memSlotNewIndex = &newIndex var addMemSize = task.addMemSize diff --git a/pkg/hostman/guestman/qemu-kvm.go b/pkg/hostman/guestman/qemu-kvm.go index bd81342ace..c417fce5f0 100644 --- a/pkg/hostman/guestman/qemu-kvm.go +++ b/pkg/hostman/guestman/qemu-kvm.go @@ -199,7 +199,7 @@ func (s *SKVMGuestInstance) reallocateNumaNodes(isMigrate bool) error { } func (s *SKVMGuestInstance) reallocateMigrateNumaNodes() error { - nodeNumaCpus, err := s.manager.cpuSet.AllocCpusetWithNodeCount(int(s.Desc.Cpu), s.Desc.Mem*1024, len(s.Desc.MemDesc.Mem.Mems)+1) + nodeNumaCpus, err := s.manager.cpuSet.AllocCpusetWithNodeCount(int(s.Desc.Cpu), s.Desc.Mem*1024, s.Desc.MemDesc.GuestNumaNodeCount()) if err != nil { return errors.Wrap(err, "AllocCpusetWithNodeCount") } @@ -223,17 +223,20 @@ func (s *SKVMGuestInstance) reallocateMigrateNumaNodes() error { if len(cpuNumaPin) > 0 { s.Desc.CpuNumaPin = cpuNumaPin - s.Desc.MemDesc.Mem.SMemDesc.SetHostNodes(int(*cpuNumaPin[0].NodeId)) - for i := range s.Desc.MemDesc.Mem.Mems { - s.Desc.MemDesc.Mem.Mems[i].SetHostNodes(int(*cpuNumaPin[i+1].NodeId)) + if s.Desc.MemDesc.Mem != nil { + s.Desc.MemDesc.Mem.SMemDesc.SetHostNodes(int(*cpuNumaPin[0].NodeId)) + for i := range s.Desc.MemDesc.Mem.Mems { + s.Desc.MemDesc.Mem.Mems[i].SetHostNodes(int(*cpuNumaPin[i+1].NodeId)) + } } } else { - s.Desc.MemDesc.Mem.SMemDesc.SetHostNodes(-1) - for i := range s.Desc.MemDesc.Mem.Mems { - s.Desc.MemDesc.Mem.Mems[i].SetHostNodes(-1) + if s.Desc.MemDesc.Mem != nil { + s.Desc.MemDesc.Mem.SMemDesc.SetHostNodes(-1) + for i := range s.Desc.MemDesc.Mem.Mems { + s.Desc.MemDesc.Mem.Mems[i].SetHostNodes(-1) + } } } - return nil } @@ -393,7 +396,7 @@ func (s *SKVMGuestInstance) initLiveDescFromSourceGuest(srcDesc *desc.SGuestDesc cpuNumaPin = s.Desc.CpuNumaPin } else { // allocate cpu numa pin local - nodeNumaCpus, err := s.manager.cpuSet.AllocCpusetWithNodeCount(int(srcDesc.Cpu), srcDesc.Mem*1024, len(srcDesc.MemDesc.Mem.Mems)+1) + nodeNumaCpus, err := s.manager.cpuSet.AllocCpusetWithNodeCount(int(srcDesc.Cpu), srcDesc.Mem*1024, srcDesc.MemDesc.GuestNumaNodeCount()) if err != nil { return errors.Wrap(err, "AllocCpusetWithNodeCount") } @@ -457,15 +460,19 @@ func (s *SKVMGuestInstance) initLiveDescFromSourceGuest(srcDesc *desc.SGuestDesc } if len(cpuNumaPin) > 0 { - srcDesc.MemDesc.Mem.SMemDesc.SetHostNodes(int(*cpuNumaPin[0].NodeId)) - for i := range srcDesc.MemDesc.Mem.Mems { - srcDesc.MemDesc.Mem.Mems[i].SetHostNodes(int(*cpuNumaPin[i+1].NodeId)) + if srcDesc.MemDesc.Mem != nil { + srcDesc.MemDesc.Mem.SMemDesc.SetHostNodes(int(*cpuNumaPin[0].NodeId)) + for i := range srcDesc.MemDesc.Mem.Mems { + srcDesc.MemDesc.Mem.Mems[i].SetHostNodes(int(*cpuNumaPin[i+1].NodeId)) + } } srcDesc.CpuNumaPin = cpuNumaPin } else { - srcDesc.MemDesc.Mem.SMemDesc.SetHostNodes(-1) - for i := range srcDesc.MemDesc.Mem.Mems { - srcDesc.MemDesc.Mem.Mems[i].SetHostNodes(-1) + if srcDesc.MemDesc.Mem != nil { + srcDesc.MemDesc.Mem.SMemDesc.SetHostNodes(-1) + for i := range srcDesc.MemDesc.Mem.Mems { + srcDesc.MemDesc.Mem.Mems[i].SetHostNodes(-1) + } } } diff --git a/pkg/hostman/guestman/qemu/generate.go b/pkg/hostman/guestman/qemu/generate.go index 298641e76f..8336df46f8 100644 --- a/pkg/hostman/guestman/qemu/generate.go +++ b/pkg/hostman/guestman/qemu/generate.go @@ -198,8 +198,10 @@ func generateMachineOption(drvOpt QemuOptions, desc *desc.SGuestDesc) string { func generateSMPOption(guestDesc *desc.SGuestDesc) string { cpu := guestDesc.CpuDesc startCpus := cpu.Cpus - if len(guestDesc.MemDesc.Mem.Mems) > 0 { - startCpus = 1 + if guestDesc.MemDesc.Mem != nil { + if len(guestDesc.MemDesc.Mem.Mems) > 0 { + startCpus = 1 + } } if cpu.MaxCpus%2 > 0 { return fmt.Sprintf(