diff --git a/pkg/apis/compute/guests.go b/pkg/apis/compute/guests.go index 464534995c..0929290c06 100644 --- a/pkg/apis/compute/guests.go +++ b/pkg/apis/compute/guests.go @@ -979,6 +979,13 @@ type ServerChangeDiskStorageInternalInput struct { CloneDiskCount int `json:"disk_count"` } +type ServerCopyDiskToStorageInput struct { + KeepOriginDisk bool `json:"keep_origin_disk"` + GuestRunning bool `json:"guest_running"` + CompletedDiskCount int `json:"completed_disk_count"` + CloneDiskCount int `json:"disk_count"` +} + type ServerSetExtraOptionInput struct { Key string `json:"key"` Value string `json:"value"` diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 89e5b0c2f7..0a8a6e0424 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -5809,7 +5809,21 @@ func (self *SGuest) PerformChangeDiskStorage(ctx context.Context, userCred mccli return nil, err } - // create a disk on target storage from source disk + { + copyInput := api.ServerCopyDiskToStorageInput{ + KeepOriginDisk: input.KeepOriginDisk, + GuestRunning: self.Status == api.VM_RUNNING, + } + err := self.CopyDiskToStorage(ctx, userCred, srcDisk, storage, copyInput, "") + if err != nil { + return nil, errors.Wrap(err, "CopyDiskToStorage") + } + } + + return nil, nil +} + +func (guest *SGuest) CopyDiskToStorage(ctx context.Context, userCred mcclient.TokenCredential, srcDisk *SDisk, storage *SStorage, input api.ServerCopyDiskToStorageInput, parentTaskId string) error { diskConf := &api.DiskConfig{ Index: -1, ImageId: srcDisk.TemplateId, @@ -5818,19 +5832,39 @@ func (self *SGuest) PerformChangeDiskStorage(ctx context.Context, userCred mccli DiskType: srcDisk.DiskType, } - targetDisk, err := self.CreateDiskOnStorage(ctx, userCred, storage, diskConf, nil, true, true) + targetDisk, err := guest.CreateDiskOnStorage(ctx, userCred, storage, diskConf, nil, true, true) if err != nil { - return nil, errors.Wrapf(err, "Create target disk on storage %s", storage.GetName()) + return errors.Wrapf(err, "Create target disk on storage %s", storage.GetName()) + } + + { + err := db.InheritFromTo(ctx, userCred, srcDisk, targetDisk) + if err != nil { + return errors.Wrapf(err, "Inherit class metadata from src %s to target %s", srcDisk.GetName(), targetDisk.GetName()) + } } internalInput := &api.ServerChangeDiskStorageInternalInput{ - ServerChangeDiskStorageInput: *input, - StorageId: srcDisk.StorageId, - TargetDiskId: targetDisk.GetId(), - GuestRunning: self.Status == api.VM_RUNNING, + ServerChangeDiskStorageInput: api.ServerChangeDiskStorageInput{ + DiskId: srcDisk.Id, + TargetStorageId: storage.Id, + KeepOriginDisk: input.KeepOriginDisk, + }, + StorageId: srcDisk.StorageId, + TargetDiskId: targetDisk.GetId(), + GuestRunning: input.GuestRunning, + CloneDiskCount: input.CloneDiskCount, + CompletedDiskCount: input.CompletedDiskCount, } - return nil, self.StartChangeDiskStorageTask(ctx, userCred, internalInput, "") + { + err := guest.StartChangeDiskStorageTask(ctx, userCred, internalInput, parentTaskId) + if err != nil { + return errors.Wrap(err, "StartChangeDiskStorageTask") + } + } + + return nil } func (self *SGuest) StartChangeDiskStorageTask(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerChangeDiskStorageInternalInput, parentTaskId string) error { diff --git a/pkg/compute/tasks/guest_change_disk_storage_task.go b/pkg/compute/tasks/guest_change_disk_storage_task.go index 86e84bf3b4..b586483bfd 100644 --- a/pkg/compute/tasks/guest_change_disk_storage_task.go +++ b/pkg/compute/tasks/guest_change_disk_storage_task.go @@ -381,36 +381,17 @@ func (t *GuestChangeDisksStorageTask) CreateTargetDisk(ctx context.Context, gues return } - // create a disk on target storage from source disk - diskConf := &api.DiskConfig{ - Index: -1, - ImageId: srcDisk.TemplateId, - SizeMb: srcDisk.DiskSize, - Fs: srcDisk.FsFormat, - DiskType: srcDisk.DiskType, - } - - targetDisk, err := guest.CreateDiskOnStorage(ctx, t.UserCred, storage, diskConf, nil, true, true) - if err != nil { - t.TaskFailed(ctx, guest, jsonutils.NewString(fmt.Sprintf("Create target disk on storage %s: %s", storage.GetName(), err))) - return - } - - internalInput := &api.ServerChangeDiskStorageInternalInput{ - ServerChangeDiskStorageInput: api.ServerChangeDiskStorageInput{ - DiskId: srcDisk.Id, - TargetStorageId: storage.Id, - KeepOriginDisk: input.KeepOriginDisk, - }, - StorageId: srcDisk.StorageId, - TargetDiskId: targetDisk.GetId(), - GuestRunning: input.GuestRunning, - CloneDiskCount: input.DiskCount, - CompletedDiskCount: input.DiskCount - len(input.Disks) - 1, - } - - if err := guest.StartChangeDiskStorageTask(ctx, t.UserCred, internalInput, t.Id); err != nil { - t.TaskFailed(ctx, guest, jsonutils.NewString(err.Error())) - return + { + copyInput := api.ServerCopyDiskToStorageInput{ + KeepOriginDisk: input.KeepOriginDisk, + GuestRunning: input.GuestRunning, + CloneDiskCount: input.DiskCount, + CompletedDiskCount: input.DiskCount - len(input.Disks) - 1, + } + err := guest.CopyDiskToStorage(ctx, t.UserCred, srcDisk, storage, copyInput, t.GetTaskId()) + if err != nil { + t.TaskFailed(ctx, guest, jsonutils.NewString(fmt.Sprintf("CopyDiskToStorage fail: %s", err))) + return + } } }