fix(region): support change storage type (#23529)

This commit is contained in:
屈轩
2025-10-14 16:59:13 +08:00
committed by GitHub
parent ad753e0df2
commit 9e0c524263
14 changed files with 192 additions and 9 deletions

View File

@@ -47,6 +47,7 @@ func init() {
cmd.Perform("migrate", &compute_options.DiskMigrateOptions{})
cmd.Perform("reset-template", &compute_options.DiskResetTemplateOptions{})
cmd.Perform("change-billing-type", new(compute_options.DiskChangeBillingTypeOptions))
cmd.Perform("change-storage-type", &compute_options.DiskChangeStorageTypeOptions{})
type DiskDetailOptions struct {
ID string `help:"ID or Name of disk"`

2
go.mod
View File

@@ -97,7 +97,7 @@ require (
k8s.io/cri-api v0.22.17
k8s.io/klog/v2 v2.20.0
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251013100607-3a8dc1b149ab
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251014082718-119f8d6bfa32
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91

4
go.sum
View File

@@ -1470,8 +1470,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251013100607-3a8dc1b149ab h1:4PW8f9gW2eoxPTSpdFAJkzskIElTWN4NkRi7gA68GK8=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251013100607-3a8dc1b149ab/go.mod h1:qn8eC11Gn4/41YJRzQcwB/G1Z3rQRxRrDNC8LDvQR48=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251014082718-119f8d6bfa32 h1:tSXqxkX61bmo65YYm0JS9CGDtoOi9WEHM4OCLZBpmGo=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251014082718-119f8d6bfa32/go.mod h1:qn8eC11Gn4/41YJRzQcwB/G1Z3rQRxRrDNC8LDvQR48=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=

View File

@@ -354,6 +354,11 @@ type DiskMigrateInput struct {
TargetStorageId string `json:"target_storage_id"`
}
type DiskChagneStorageTypeInput struct {
// 目标存储类型
StorageType string `json:"storage_type"`
}
type DiskSnapshotpolicyInput struct {
SnapshotpolicyId string `json:"snapshotpolicy_id"`
}

View File

@@ -1077,6 +1077,40 @@ func (self *SDisk) PerformMigrate(ctx context.Context, userCred mcclient.TokenCr
return nil, task.ScheduleRun(nil)
}
func (self *SDisk) PerformChangeStorageType(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.DiskChagneStorageTypeInput) (jsonutils.JSONObject, error) {
if len(input.StorageType) == 0 {
return nil, httperrors.NewMissingParameterError("storage_type")
}
storage, err := self.GetStorage()
if err != nil {
return nil, errors.Wrapf(err, "GetStorage")
}
if storage.StorageType == input.StorageType {
return nil, httperrors.NewInputParameterError("Storage type is already %s", input.StorageType)
}
storages := []SStorage{}
q := StorageManager.Query().Equals("zone_id", storage.ZoneId).Equals("storage_type", input.StorageType).IsTrue("enabled").Equals("status", api.STORAGE_ONLINE).Equals("manager_id", storage.ManagerId)
err = q.All(&storages)
if err != nil {
return nil, errors.Wrapf(err, "CountWithError")
}
if len(storages) == 0 {
return nil, httperrors.NewInputParameterError("no available storage type %s to change", input.StorageType)
}
if len(storages) > 1 {
return nil, httperrors.NewInputParameterError("duplicate storage type %s found", input.StorageType)
}
self.SetStatus(ctx, userCred, api.DISK_MIGRATING, "")
params := jsonutils.NewDict()
params.Set("storage_id", jsonutils.NewString(storages[0].Id))
task, err := taskman.TaskManager.NewTask(ctx, "DiskChangeStorageTypeTask", self, userCred, params, "", "", nil)
if err != nil {
return nil, errors.Wrapf(err, "NewTask")
}
return nil, task.ScheduleRun(nil)
}
func (self *SDisk) GetSchedMigrateParams(targetStorageId string) (*schedapi.ScheduleInput, error) {
diskConfig := self.ToDiskConfig()
diskConfig.Medium = ""

View File

@@ -0,0 +1,86 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package disk
import (
"context"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
type DiskChangeStorageTypeTask struct {
SDiskBaseTask
}
func init() {
taskman.RegisterTask(DiskChangeStorageTypeTask{})
}
func (self *DiskChangeStorageTypeTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
disk := obj.(*models.SDisk)
idisk, err := disk.GetIDisk(ctx)
if err != nil {
self.taskFail(ctx, disk, errors.Wrapf(err, "GetIDisk"))
return
}
storageId, err := self.GetParams().GetString("storage_id")
if err != nil {
self.taskFail(ctx, disk, errors.Wrapf(err, "get storage_id"))
return
}
storageObj, err := models.StorageManager.FetchById(storageId)
if err != nil {
self.taskFail(ctx, disk, errors.Wrapf(err, "fetch storage by id"))
return
}
storage := storageObj.(*models.SStorage)
opts := &cloudprovider.ChangeStorageOptions{
DiskId: disk.ExternalId,
StorageType: storage.StorageType,
}
err = idisk.ChangeStorage(ctx, opts)
if err != nil {
self.taskFail(ctx, disk, errors.Wrapf(err, "ChangeStorage"))
return
}
db.Update(disk, func() error {
disk.StorageId = storage.Id
disk.Status = api.DISK_READY
return nil
})
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_MIGRATE, opts.StorageType, self.UserCred, true)
self.SetStageComplete(ctx, nil)
}
func (self *DiskChangeStorageTypeTask) taskFail(ctx context.Context, disk *models.SDisk, err error) {
disk.SetStatus(ctx, self.GetUserCred(), api.DISK_MIGRATE_FAIL, "")
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_MIGRATE, err, self.UserCred, false)
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
}

View File

@@ -28,8 +28,7 @@ import (
)
type SDisk struct {
multicloud.SVirtualResourceBase
multicloud.SBillingBase
multicloud.SDisk
CloudpodsTags
region *SRegion

View File

@@ -92,6 +92,20 @@ func (o *DiskMigrateOptions) Params() (jsonutils.JSONObject, error) {
return options.StructToParams(o)
}
type DiskChangeStorageTypeOptions struct {
ID string `help:"ID of the server" json:"-"`
StorageType string `help:"Disk migrate target storage type" json:"storage_type"`
}
func (o *DiskChangeStorageTypeOptions) GetId() string {
return o.ID
}
func (o *DiskChangeStorageTypeOptions) Params() (jsonutils.JSONObject, error) {
return options.StructToParams(o)
}
type DiskResetTemplateOptions struct {
ID string `help:"ID of the server" json:"-"`

2
vendor/modules.txt vendored
View File

@@ -2037,7 +2037,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251013100607-3a8dc1b149ab
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251014082718-119f8d6bfa32
## explicit; go 1.24
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing

View File

@@ -26,3 +26,8 @@ type DiskCreateConfig struct {
Tags map[string]string
}
type ChangeStorageOptions struct {
StorageType string
DiskId string
}

View File

@@ -573,6 +573,7 @@ type ICloudDisk interface {
Rebuild(ctx context.Context) error
GetPreallocation() string
ChangeStorage(ctx context.Context, opts *ChangeStorageOptions) error
}
type ICloudSnapshot interface {

View File

@@ -471,3 +471,28 @@ func (self *SRegion) rebuildDisk(diskId string) error {
func (self *SDisk) GetProjectId() string {
return self.ResourceGroupId
}
func (region *SRegion) ChagneDiskStorage(ctx context.Context, opts *cloudprovider.ChangeStorageOptions) error {
params := map[string]string{
"DiskId": opts.DiskId,
"DiskCategory": opts.StorageType,
}
switch opts.StorageType {
case api.STORAGE_CLOUD_ESSD_PL0:
params["DiskCategory"] = api.STORAGE_CLOUD_ESSD
params["PerformanceLevel"] = "PL0"
case api.STORAGE_CLOUD_ESSD_PL2:
params["DiskCategory"] = api.STORAGE_CLOUD_ESSD
params["PerformanceLevel"] = "PL2"
case api.STORAGE_CLOUD_ESSD_PL3:
params["DiskCategory"] = api.STORAGE_CLOUD_ESSD
params["PerformanceLevel"] = "PL3"
}
_, err := region.ecsRequest("ModifyDiskSpec", params)
return err
}
func (disk *SDisk) ChangeStorage(ctx context.Context, opts *cloudprovider.ChangeStorageOptions) error {
opts.DiskId = disk.DiskId
return disk.storage.zone.region.ChagneDiskStorage(ctx, opts)
}

View File

@@ -15,7 +15,11 @@
package multicloud
import (
"context"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/pkg/errors"
)
type SDisk struct {
@@ -23,14 +27,18 @@ type SDisk struct {
SBillingBase
}
func (self *SDisk) GetIStorageId() string {
func (disk *SDisk) GetIStorageId() string {
return ""
}
func (self *SDisk) GetIops() int {
func (disk *SDisk) GetIops() int {
return 0
}
func (self *SDisk) GetPreallocation() string {
func (disk *SDisk) GetPreallocation() string {
return api.DISK_PREALLOCATION_OFF
}
func (disk *SDisk) ChangeStorage(ctx context.Context, opts *cloudprovider.ChangeStorageOptions) error {
return errors.Wrapf(cloudprovider.ErrNotImplemented, "ChangeStorage")
}

View File

@@ -20,6 +20,7 @@ import (
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/pkg/errors"
)
type SDisk struct {
@@ -134,3 +135,7 @@ func (self *SDisk) Rebuild(ctx context.Context) error {
func (disk *SDisk) SetStorage(storage SStorage) {
disk.storage = &storage
}
func (disk *SDisk) ChangeStorage(ctx context.Context, opts *cloudprovider.ChangeStorageOptions) error {
return errors.Wrapf(cloudprovider.ErrNotImplemented, "ChangeStorage")
}