fix(llm): harden volume resize and update size log (#24670)

- Wait for disk/desktop status after resize via backup worker
- Centralize volume SizeMB update with resize action log
- Expose vCPU/memory fields in LLM customize columns
This commit is contained in:
Zexi Li
2026-04-13 14:39:02 +08:00
committed by GitHub
parent 71cf58d63d
commit fc6079ed86
4 changed files with 74 additions and 51 deletions
+1
View File
@@ -152,6 +152,7 @@ type LLMSkuBaseUpdateInput struct {
// RequstSyncImage *bool `json:"request_sync_image"`
DiskSize *int `json:"disk_size" yunion-deprecated-by:"disk_size_mb"`
DiskSizeMB *int `json:"disk_size_mb"`
TemplateId *string `json:"template_id"`
StorageType *string `json:"storage_type"`
+2
View File
@@ -318,6 +318,8 @@ func (man *SLLMManager) FetchCustomizeColumns(
res[i].HostEIP = guest.HostEIP
res[i].Zone = guest.Zone
res[i].ZoneId = guest.ZoneId
res[i].VcpuCount = guest.VcpuCount
res[i].VmemSizeMb = guest.VmemSize
adbMappedPort := -1
// for j := range res[i].AccessInfo {
+25
View File
@@ -25,6 +25,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/mcclient/modules/image"
"yunion.io/x/onecloud/pkg/util/logclient"
)
func init() {
@@ -247,3 +248,27 @@ func (volume *SVolume) DoReset(ctx context.Context, userCred mcclient.TokenCrede
return nil
}
func (volume *SVolume) UpdateSize(ctx context.Context, userCred mcclient.TokenCredential, sizeMb int) error {
if volume.SizeMB == sizeMb {
return nil
}
oldSize := volume.SizeMB
_, err := db.Update(volume, func() error {
volume.SizeMB = sizeMb
return nil
})
if err != nil {
logclient.AddSimpleActionLog(volume, logclient.ACT_RESIZE, err, userCred, false)
return errors.Wrap(err, "update volume size")
}
notes := struct {
OldSizeMb int `json:"old_size_mb"`
NewSizeMb int `json:"new_size_mb"`
}{
OldSizeMb: oldSize,
NewSizeMb: sizeMb,
}
logclient.AddSimpleActionLog(volume, logclient.ACT_RESIZE, jsonutils.Marshal(notes), userCred, true)
return nil
}
+46 -51
View File
@@ -8,11 +8,11 @@ import (
"yunion.io/x/pkg/errors"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
api "yunion.io/x/onecloud/pkg/apis/llm"
llmapi "yunion.io/x/onecloud/pkg/apis/llm"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/llm/models"
"yunion.io/x/onecloud/pkg/llm/tasks/worker"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/util/logclient"
@@ -28,71 +28,66 @@ func init() {
func (task *VolumeResizeTask) taskFailed(ctx context.Context, volume *models.SVolume, err error) {
volume.SetStatus(ctx, task.UserCred, computeapi.DISK_RESIZE_FAILED, err.Error())
db.OpsLog.LogEvent(volume, "resize", err, task.UserCred)
logclient.AddActionLogWithStartable(task, volume, "resize", err.Error(), task.UserCred, false)
db.OpsLog.LogEvent(volume, db.ACT_RESIZE_FAIL, err, task.UserCred)
logclient.AddActionLogWithStartable(task, volume, logclient.ACT_RESIZE, err.Error(), task.UserCred, false)
task.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
}
func (task *VolumeResizeTask) taskComplete(ctx context.Context, volume *models.SVolume) {
volume.SetStatus(ctx, task.UserCred, computeapi.DISK_READY, "")
volume.SetStatus(ctx, task.UserCred, computeapi.DISK_READY, "resize success")
logclient.AddActionLogWithStartable(task, volume, logclient.ACT_RESIZE, nil, task.UserCred, true)
task.SetStageComplete(ctx, nil)
}
func (task *VolumeResizeTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
volume := obj.(*models.SVolume)
input := api.VolumeResizeTaskInput{}
if task.GetParams() != nil {
_ = task.GetParams().Unmarshal(&input)
}
if input.SizeMB <= 0 {
task.taskFailed(ctx, volume, errors.Wrap(httperrors.ErrInputParameter, "missing size_mb"))
return
}
if volume.SizeMB >= input.SizeMB {
task.taskComplete(ctx, volume)
return
}
if len(volume.CmpId) == 0 {
task.taskFailed(ctx, volume, errors.Wrap(errors.ErrInvalidStatus, "empty cmp_id"))
return
}
// Resize disk
s := auth.GetSession(ctx, task.UserCred, "")
params := jsonutils.NewDict()
params.Set("size", jsonutils.NewString(fmt.Sprintf("%dM", input.SizeMB)))
task.SetStage("OnDiskResizeComplete", nil)
err := s.WithTaskCallback(task.GetId(), func() error {
_, err := compute.Disks.PerformAction(s, volume.CmpId, "resize", params)
return err
})
input := llmapi.VolumeResizeTaskInput{}
err := task.Params.Unmarshal(&input)
if err != nil {
task.taskFailed(ctx, volume, errors.Wrap(err, "disk resize"))
task.taskFailed(ctx, volume, errors.Wrap(err, "Unmarshal SVolumeResizeTaskInput"))
return
}
volume.SetStatus(ctx, task.UserCred, llmapi.VOLUME_STATUS_RESIZING, "resizing")
if int(input.SizeMB) > volume.SizeMB {
// need to resize disk
s := auth.GetSession(ctx, task.UserCred, "")
params := computeapi.DiskResizeInput{}
params.Size = fmt.Sprintf("%dM", input.SizeMB)
_, err := compute.Disks.PerformAction(s, volume.CmpId, "resize", jsonutils.Marshal(params))
if err != nil {
task.taskFailed(ctx, volume, errors.Wrap(err, "disk resize"))
return
}
task.SetStage("OnDiskResizeComplete", nil)
worker.BackupTaskRun(task, func() (jsonutils.JSONObject, error) {
_, err := volume.WaitDiskStatus(ctx, task.UserCred, []string{computeapi.DISK_READY}, 3600)
if err != nil {
return nil, errors.Wrap(err, "WaitDiskStatus")
}
d := volume.GetLLM()
if d != nil && len(input.DesktopStatus) > 0 {
_, err = d.WaitServerStatus(ctx, task.UserCred, []string{input.DesktopStatus}, 3600)
if err != nil {
return nil, errors.Wrap(err, "WaitServerStatus")
}
}
// update volume size
err = volume.UpdateSize(ctx, task.UserCred, input.SizeMB)
if err != nil {
return nil, errors.Wrap(err, "UpdateSize")
}
return nil, nil
})
} else {
task.OnDiskResizeComplete(ctx, volume, nil)
}
}
func (task *VolumeResizeTask) OnDiskResizeComplete(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
volume := obj.(*models.SVolume)
input := api.VolumeResizeTaskInput{}
if task.GetParams() != nil {
_ = task.GetParams().Unmarshal(&input)
}
if _, err := volume.WaitDiskStatus(ctx, task.UserCred, []string{computeapi.DISK_READY}, 7200); err != nil {
task.taskFailed(ctx, volume, err)
return
}
_, err := db.Update(volume, func() error {
volume.SizeMB = input.SizeMB
return nil
})
if err != nil {
task.taskFailed(ctx, volume, errors.Wrap(err, "update volume size_mb"))
return
}
task.taskComplete(ctx, volume)
}