diff --git a/pkg/compute/tasks/disk_resize_task.go b/pkg/compute/tasks/disk_resize_task.go index 4fd8297731..4c8f694d01 100644 --- a/pkg/compute/tasks/disk_resize_task.go +++ b/pkg/compute/tasks/disk_resize_task.go @@ -52,7 +52,7 @@ func (self *DiskResizeTask) OnInit(ctx context.Context, obj db.IStandaloneModel, storage, _ := disk.GetStorage() guest := disk.GetGuest() - if guest != nil && guest.PowerStates == api.VM_POWER_STATES_ON { + if guest != nil { host, _ = guest.GetHost() } else { host, _ = storage.GetMasterHost() diff --git a/pkg/hostman/guestman/guestman.go b/pkg/hostman/guestman/guestman.go index 37a0826e20..36b24decb1 100644 --- a/pkg/hostman/guestman/guestman.go +++ b/pkg/hostman/guestman/guestman.go @@ -1367,13 +1367,13 @@ func (m *SGuestManager) Resume(ctx context.Context, sid string, isLiveMigrate bo return nil, nil } -func (m *SGuestManager) OnlineResizeDisk(ctx context.Context, sid string, diskId string, sizeMb int64) (jsonutils.JSONObject, error) { +func (m *SGuestManager) OnlineResizeDisk(ctx context.Context, sid string, disk storageman.IDisk, sizeMb int64) (jsonutils.JSONObject, error) { guest, ok := m.GetServer(sid) if !ok { return nil, httperrors.NewNotFoundError("guest %s not found", sid) } if guest.IsRunning() { - guest.onlineResizeDisk(ctx, diskId, sizeMb) + guest.onlineResizeDisk(ctx, disk, sizeMb) return nil, nil } else { return nil, httperrors.NewInvalidStatusError("guest is not runnign") diff --git a/pkg/hostman/guestman/guesttasks.go b/pkg/hostman/guestman/guesttasks.go index 3118c2d92b..1c655c708b 100644 --- a/pkg/hostman/guestman/guesttasks.go +++ b/pkg/hostman/guestman/guesttasks.go @@ -2317,17 +2317,17 @@ type SGuestOnlineResizeDiskTask struct { *SKVMGuestInstance ctx context.Context - diskId string + disk storageman.IDisk sizeMB int64 } func NewGuestOnlineResizeDiskTask( - ctx context.Context, s *SKVMGuestInstance, diskId string, sizeMB int64, + ctx context.Context, s *SKVMGuestInstance, disk storageman.IDisk, sizeMB int64, ) *SGuestOnlineResizeDiskTask { return &SGuestOnlineResizeDiskTask{ SKVMGuestInstance: s, ctx: ctx, - diskId: diskId, + disk: disk, sizeMB: sizeMB, } } @@ -2349,12 +2349,16 @@ func (task *SGuestOnlineResizeDiskTask) OnGetBlocksSucc(blocks []monitor.QemuBlo } image, _ = fileJson.GetString("file", "image") } - if len(blocks[i].Inserted.File) > 0 && strings.HasSuffix(blocks[i].Inserted.File, task.diskId) || image == task.diskId { + if len(blocks[i].Inserted.File) > 0 && strings.HasSuffix(blocks[i].Inserted.File, task.disk.GetId()) || image == task.disk.GetId() { + if err := task.disk.PreResize(task.ctx, task.sizeMB); err != nil { + hostutils.TaskFailed(task.ctx, fmt.Sprintf("disk %s preResize failed %s", task.disk.GetId(), err)) + return + } task.Monitor.ResizeDisk(blocks[i].Device, task.sizeMB, task.OnResizeSucc) return } } - hostutils.TaskFailed(task.ctx, fmt.Sprintf("disk %s not found on this guest", task.diskId)) + hostutils.TaskFailed(task.ctx, fmt.Sprintf("disk %s not found on this guest", task.disk.GetId())) } func (task *SGuestOnlineResizeDiskTask) OnResizeSucc(err string) { @@ -2364,7 +2368,7 @@ func (task *SGuestOnlineResizeDiskTask) OnResizeSucc(err string) { hostutils.TaskComplete(task.ctx, params) return } - hostutils.TaskFailed(task.ctx, fmt.Sprintf("resize disk %s %dMb error: %v", task.diskId, task.sizeMB, err)) + hostutils.TaskFailed(task.ctx, fmt.Sprintf("resize disk %s %dMb error: %v", task.disk.GetId(), task.sizeMB, err)) } /** diff --git a/pkg/hostman/guestman/qemu-kvm.go b/pkg/hostman/guestman/qemu-kvm.go index 095453c6ae..d6f51d00ad 100644 --- a/pkg/hostman/guestman/qemu-kvm.go +++ b/pkg/hostman/guestman/qemu-kvm.go @@ -3413,8 +3413,8 @@ func (s *SKVMGuestInstance) prepareNicsForVolatileGuestResume() error { return nil } -func (s *SKVMGuestInstance) onlineResizeDisk(ctx context.Context, diskId string, sizeMB int64) { - task := NewGuestOnlineResizeDiskTask(ctx, s, diskId, sizeMB) +func (s *SKVMGuestInstance) onlineResizeDisk(ctx context.Context, disk storageman.IDisk, sizeMB int64) { + task := NewGuestOnlineResizeDiskTask(ctx, s, disk, sizeMB) task.Start() } diff --git a/pkg/hostman/storageman/disk_base.go b/pkg/hostman/storageman/disk_base.go index 512d5df4c9..f7323c4bc2 100644 --- a/pkg/hostman/storageman/disk_base.go +++ b/pkg/hostman/storageman/disk_base.go @@ -54,6 +54,7 @@ type IDisk interface { DiskDeleteSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) + PreResize(ctx context.Context, sizeMb int64) error PrepareSaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) CleanupSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) @@ -132,6 +133,10 @@ func (d *SBaseDisk) Resize(context.Context, interface{}) (jsonutils.JSONObject, return nil, errors.Errorf("unsupported operation") } +func (d *SBaseDisk) PreResize(ctx context.Context, sizeMb int64) error { + return nil +} + func (d *SBaseDisk) CreateSnapshot(snapshotId string, encryptKey string, encFormat qemuimg.TEncryptFormat, encAlg seclib2.TSymEncAlg) error { return errors.Errorf("unsupported operation") } diff --git a/pkg/hostman/storageman/disk_lvm.go b/pkg/hostman/storageman/disk_lvm.go index 8eded53d51..7ebdbf4350 100644 --- a/pkg/hostman/storageman/disk_lvm.go +++ b/pkg/hostman/storageman/disk_lvm.go @@ -237,6 +237,24 @@ func (d *SLVMDisk) OnRebuildRoot(ctx context.Context, params api.DiskAllocateInp return err } +func (d *SLVMDisk) PreResize(ctx context.Context, sizeMb int64) error { + qemuImg, err := qemuimg.NewQemuImage(d.GetPath()) + if err != nil { + return errors.Wrap(err, "lvm qemuimg.NewQemuImage") + } + + lvsize := sizeMb + if qemuImg.Format == qemuimgfmt.QCOW2 { + lvsize = lvmutils.GetQcow2LvSize(sizeMb) + } + + err = lvmutils.LvResize(d.Storage.GetPath(), d.GetPath(), lvsize*1024*1024) + if err != nil { + return errors.Wrap(err, "lv resize") + } + return nil +} + func (d *SLVMDisk) Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) { diskInfo, ok := params.(*jsonutils.JSONDict) if !ok { diff --git a/pkg/hostman/storageman/disk_slvm.go b/pkg/hostman/storageman/disk_slvm.go index 8fac375e43..f25c93a686 100644 --- a/pkg/hostman/storageman/disk_slvm.go +++ b/pkg/hostman/storageman/disk_slvm.go @@ -117,6 +117,46 @@ func (d *SSLVMDisk) CreateFromTemplate( return ret, nil } +func (d *SSLVMDisk) PreResize(ctx context.Context, sizeMb int64) error { + if ok, err := lvmutils.LvIsActivated(d.GetPath()); err != nil { + return err + } else if ok && d.Storage.Lvmlockd() { + err = lvmutils.LVActive(d.GetPath(), false, true) + if err != nil { + return errors.Wrap(err, "lvactive shared") + } + } + err := d.SLVMDisk.PreResize(ctx, sizeMb) + if err != nil { + return err + } + err = lvmutils.LVActive(d.GetPath(), d.Storage.Lvmlockd(), false) + if err != nil { + return errors.Wrap(err, "lvactive shared") + } + return nil +} + +func (d *SSLVMDisk) Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) { + if ok, err := lvmutils.LvIsActivated(d.GetPath()); err != nil { + return nil, err + } else if ok && d.Storage.Lvmlockd() { + err = lvmutils.LVActive(d.GetPath(), false, true) + if err != nil { + return nil, errors.Wrap(err, "lvactive shared") + } + } + ret, err := d.SLVMDisk.Resize(ctx, params) + if err != nil { + return ret, err + } + err = lvmutils.LVActive(d.GetPath(), d.Storage.Lvmlockd(), false) + if err != nil { + return ret, errors.Wrap(err, "lvactive shared") + } + return ret, nil +} + func (d *SSLVMDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) { var lvPath = d.GetPath() activated, err := lvmutils.LvIsActivated(lvPath) diff --git a/pkg/hostman/storageman/diskhandlers/diskhandler.go b/pkg/hostman/storageman/diskhandlers/diskhandler.go index b85c2a09e6..6e9d8aae8b 100644 --- a/pkg/hostman/storageman/diskhandlers/diskhandler.go +++ b/pkg/hostman/storageman/diskhandlers/diskhandler.go @@ -306,7 +306,7 @@ func diskResize(ctx context.Context, userCred mcclient.TokenCredential, storage serverId, _ := diskInfo.GetString("server_id") if len(serverId) > 0 && guestman.GetGuestManager().Status(serverId) == "running" { sizeMb, _ := diskInfo.Int("size") - return guestman.GetGuestManager().OnlineResizeDisk(ctx, serverId, diskId, sizeMb) + return guestman.GetGuestManager().OnlineResizeDisk(ctx, serverId, disk, sizeMb) } else { hostutils.DelayTask(ctx, disk.Resize, diskInfo) return nil, nil