mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #630 in YUNIONIO/onecloud from ~QUXUAN/onecloud:hotfix/qx-validate-create-disk to release/2.3.0
* commit '719a8a1db572243337194fc71c58cc12357ae075': 检查磁盘扩容大小 检查公有云磁盘创建限制
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
type SAliyunHostDriver struct {
|
||||
@@ -28,6 +29,21 @@ func (self *SAliyunHostDriver) GetHostType() string {
|
||||
return models.HOST_TYPE_ALIYUN
|
||||
}
|
||||
|
||||
func (self *SAliyunHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
if utils.IsInStringArray(storage.StorageType, []string{models.STORAGE_CLOUD_EFFICIENCY, models.STORAGE_CLOUD_SSD, models.STORAGE_CLOUD_ESSD}) {
|
||||
if sizeGb < 20 || sizeGb > 32768 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 20G ~ 32768GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == models.STORAGE_PUBLIC_CLOUD {
|
||||
if sizeGb < 5 || sizeGb > 2000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 5G ~ 2000GB", storage.StorageType)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Not support create %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAliyunHostDriver) CheckAndSetCacheImage(ctx context.Context, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
|
||||
params := task.GetParams()
|
||||
imageId, err := params.GetString("image_id")
|
||||
|
||||
@@ -3,11 +3,13 @@ package hostdrivers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
@@ -22,6 +24,29 @@ func (self *SAwsHostDriver) GetHostType() string {
|
||||
return models.HOST_TYPE_AWS
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
if storage.StorageType == models.STORAGE_GP2_SSD {
|
||||
if sizeGb < 1 || sizeGb > 16384 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 1G ~ 16384GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == models.STORAGE_IO1_SSD {
|
||||
if sizeGb < 4 || sizeGb > 16384 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 4G ~ 16384GB", storage.StorageType)
|
||||
}
|
||||
} else if utils.IsInStringArray(storage.StorageType, []string{models.STORAGE_ST1_HDD, models.STORAGE_SC1_SSD}) {
|
||||
if sizeGb < 500 || sizeGb > 16384 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 500G ~ 16384GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == models.STORAGE_STANDARD_SSD {
|
||||
if sizeGb < 1 || sizeGb > 1024 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 1G ~ 1024GB", storage.StorageType)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Not support create %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) CheckAndSetCacheImage(ctx context.Context, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
|
||||
params := task.GetParams()
|
||||
imageId, err := params.GetString("image_id")
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
type SAzureHostDriver struct {
|
||||
@@ -36,6 +37,17 @@ func (self *SAzureHostDriver) ValidateUpdateDisk(ctx context.Context, userCred m
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SAzureHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
if utils.IsInStringArray(storage.StorageType, []string{models.STORAGE_STANDARD_LRS, models.STORAGE_STANDARDSSD_LRS, models.STORAGE_PREMIUM_LRS}) {
|
||||
if sizeGb < 1 || sizeGb > 4095 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 1G ~ 4095GB", storage.StorageType)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Not support create %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAzureHostDriver) CheckAndSetCacheImage(ctx context.Context, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
|
||||
params := task.GetParams()
|
||||
imageId, err := params.GetString("image_id")
|
||||
|
||||
@@ -20,6 +20,10 @@ func (self *SBaseHostDriver) ValidateUpdateDisk(ctx context.Context, userCred mc
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
return fmt.Errorf("Not Implement ValidateDiskSize")
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) RequestDeleteSnapshotsWithStorage(ctx context.Context, host *models.SHost, snapshot *models.SSnapshot, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ func (self *SKVMHostDriver) GetHostType() string {
|
||||
return models.HOST_TYPE_HYPERVISOR
|
||||
}
|
||||
|
||||
func (self *SKVMHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMHostDriver) CheckAndSetCacheImage(ctx context.Context, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
|
||||
params := task.GetParams()
|
||||
imageId, err := params.GetString("image_id")
|
||||
|
||||
@@ -28,6 +28,28 @@ func (self *SQcloudHostDriver) GetHostType() string {
|
||||
return models.HOST_TYPE_QCLOUD
|
||||
}
|
||||
|
||||
func (self *SQcloudHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
if sizeGb%10 != 0 {
|
||||
return fmt.Errorf("The disk size must be a multiple of 10Gb")
|
||||
}
|
||||
if storage.StorageType == models.STORAGE_CLOUD_BASIC {
|
||||
if sizeGb < 10 || sizeGb > 16000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 10 ~ 16000GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == models.STORAGE_CLOUD_PREMIUM {
|
||||
if sizeGb < 50 || sizeGb > 16000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 50 ~ 16000GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == models.STORAGE_CLOUD_SSD {
|
||||
if sizeGb < 100 || sizeGb > 16000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 100 ~ 16000GB", storage.StorageType)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Not support create %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SQcloudHostDriver) CheckAndSetCacheImage(ctx context.Context, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
|
||||
params := task.GetParams()
|
||||
imageId, err := params.GetString("image_id")
|
||||
|
||||
+25
-24
@@ -293,7 +293,7 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
if _, err := manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pendingUsage := SQuota{Storage: diskConfig.Size}
|
||||
pendingUsage := SQuota{Storage: diskConfig.SizeMb}
|
||||
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, userCred.GetProjectId(), &pendingUsage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -310,14 +310,10 @@ func (manager *SDiskManager) validateDiskOnStorage(diskConfig *SDiskConfig, stor
|
||||
if storage.StorageType != diskConfig.Backend {
|
||||
return httperrors.NewInputParameterError("Storage type[%s] not match backend %s", storage.StorageType, diskConfig.Backend)
|
||||
}
|
||||
size := diskConfig.Size >> 10
|
||||
if storage.StorageType == STORAGE_CLOUD_EFFICIENCY || storage.StorageType == STORAGE_CLOUD_SSD {
|
||||
if size < 20 || size > 32768 {
|
||||
return httperrors.NewInputParameterError("cloud_ssd or cloud_efficiency disk only support 20G ~ 32768G")
|
||||
}
|
||||
} else if storage.StorageType == STORAGE_PUBLIC_CLOUD {
|
||||
if size < 5 || size > 2000 {
|
||||
return httperrors.NewInputParameterError("cloud disk only support 5G ~ 2000G")
|
||||
if host := storage.GetMasterHost(); host != nil {
|
||||
//公有云磁盘大小检查。
|
||||
if err := host.GetHostDriver().ValidateDiskSize(storage, diskConfig.SizeMb>>10); err != nil {
|
||||
return httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
}
|
||||
hoststorages := HoststorageManager.Query().SubQuery()
|
||||
@@ -328,7 +324,7 @@ func (manager *SDiskManager) validateDiskOnStorage(diskConfig *SDiskConfig, stor
|
||||
if len(hoststorage) == 0 {
|
||||
return httperrors.NewInputParameterError("Storage[%s] must attach to a host", storage.Name)
|
||||
}
|
||||
if diskConfig.Size > storage.GetFreeCapacity() && !storage.IsEmulated {
|
||||
if diskConfig.SizeMb > storage.GetFreeCapacity() && !storage.IsEmulated {
|
||||
return httperrors.NewInputParameterError("Not enough free space")
|
||||
}
|
||||
return nil
|
||||
@@ -568,21 +564,26 @@ func (self *SDisk) PerformResize(ctx context.Context, userCred mcclient.TokenCre
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size, err := fileutils.GetSizeMb(sizeStr, 'M', 1024)
|
||||
sizeMb, err := fileutils.GetSizeMb(sizeStr, 'M', 1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if self.Status != DISK_READY {
|
||||
return nil, httperrors.NewResourceNotReadyError("Resize disk when disk is READY")
|
||||
}
|
||||
if size < self.DiskSize {
|
||||
if sizeMb < self.DiskSize {
|
||||
return nil, httperrors.NewUnsupportOperationError("Disk cannot be thrink")
|
||||
}
|
||||
if size == self.DiskSize {
|
||||
if sizeMb == self.DiskSize {
|
||||
return nil, nil
|
||||
}
|
||||
addDisk := size - self.DiskSize
|
||||
addDisk := sizeMb - self.DiskSize
|
||||
storage := self.GetStorage()
|
||||
if host := storage.GetMasterHost(); host != nil {
|
||||
if err := host.GetHostDriver().ValidateDiskSize(storage, sizeMb>>10); err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
}
|
||||
if addDisk > storage.GetFreeCapacity() && !storage.IsEmulated {
|
||||
return nil, httperrors.NewOutOfResourceError("Not enough free space")
|
||||
}
|
||||
@@ -595,7 +596,7 @@ func (self *SDisk) PerformResize(ctx context.Context, userCred mcclient.TokenCre
|
||||
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, userCred.GetProjectId(), &pendingUsage); err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError(err.Error())
|
||||
}
|
||||
return nil, self.StartDiskResizeTask(ctx, userCred, int64(size), "", &pendingUsage)
|
||||
return nil, self.StartDiskResizeTask(ctx, userCred, int64(sizeMb), "", &pendingUsage)
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
|
||||
@@ -968,7 +969,7 @@ func totalDiskSize(projectId string, active tristate.TriState, ready tristate.Tr
|
||||
type SDiskConfig struct {
|
||||
ImageId string
|
||||
// ImageDiskFormat string
|
||||
Size int // MB
|
||||
SizeMb int // MB
|
||||
Fs string // file system
|
||||
Format string //
|
||||
Driver string //
|
||||
@@ -1006,7 +1007,7 @@ func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info
|
||||
continue
|
||||
}
|
||||
if regutils.MatchSize(p) {
|
||||
diskConfig.Size, _ = fileutils.GetSizeMb(p, 'M', 1024)
|
||||
diskConfig.SizeMb, _ = fileutils.GetSizeMb(p, 'M', 1024)
|
||||
} else if utils.IsInStringArray(p, osprofile.FS_TYPES) {
|
||||
diskConfig.Fs = p
|
||||
} else if utils.IsInStringArray(p, osprofile.IMAGE_FORMAT_TYPES) {
|
||||
@@ -1020,7 +1021,7 @@ func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info
|
||||
} else if p[0] == '/' {
|
||||
diskConfig.Mountpoint = p
|
||||
} else if p == "autoextend" {
|
||||
diskConfig.Size = -1
|
||||
diskConfig.SizeMb = -1
|
||||
} else if utils.IsInStringArray(p, STORAGE_TYPES) {
|
||||
diskConfig.Backend = p
|
||||
} else if len(p) > 0 {
|
||||
@@ -1042,15 +1043,15 @@ func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info
|
||||
}
|
||||
// diskConfig.ImageDiskFormat = image.DiskFormat
|
||||
CachedimageManager.ImageAddRefCount(image.Id)
|
||||
if diskConfig.Size == 0 {
|
||||
diskConfig.Size = image.MinDisk // MB
|
||||
if diskConfig.SizeMb == 0 {
|
||||
diskConfig.SizeMb = image.MinDisk // MB
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(diskConfig.ImageId) > 0 && diskConfig.Size == 0 {
|
||||
diskConfig.Size = options.Options.DefaultDiskSize // MB
|
||||
} else if len(diskConfig.ImageId) == 0 && diskConfig.Size == 0 {
|
||||
if len(diskConfig.ImageId) > 0 && diskConfig.SizeMb == 0 {
|
||||
diskConfig.SizeMb = options.Options.DefaultDiskSize // MB
|
||||
} else if len(diskConfig.ImageId) == 0 && diskConfig.SizeMb == 0 {
|
||||
return nil, httperrors.NewInputParameterError("Diskinfo not contains either imageID or size")
|
||||
}
|
||||
return &diskConfig, nil
|
||||
@@ -1086,7 +1087,7 @@ func (self *SDisk) fetchDiskInfo(diskConfig *SDiskConfig) {
|
||||
self.Nonpersistent = false
|
||||
}
|
||||
self.DiskFormat = diskConfig.Format
|
||||
self.DiskSize = diskConfig.Size
|
||||
self.DiskSize = diskConfig.SizeMb
|
||||
}
|
||||
|
||||
type DiskInfo struct {
|
||||
|
||||
@@ -834,11 +834,11 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
}
|
||||
disksConf.Set(diskSeq, jsonutils.Marshal(diskInfo))
|
||||
if _, ok := diskSizes[diskInfo.Backend]; !ok {
|
||||
diskSizes[diskInfo.Backend] = diskInfo.Size
|
||||
diskSizes[diskInfo.Backend] = diskInfo.SizeMb
|
||||
} else {
|
||||
diskSizes[diskInfo.Backend] += diskInfo.Size
|
||||
diskSizes[diskInfo.Backend] += diskInfo.SizeMb
|
||||
}
|
||||
diskSize += diskInfo.Size
|
||||
diskSize += diskInfo.SizeMb
|
||||
diskIdx += 1
|
||||
diskSeq = fmt.Sprintf("disk.%d", diskIdx)
|
||||
}
|
||||
@@ -1193,11 +1193,11 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
if len(diskConf.Backend) == 0 {
|
||||
diskConf.Backend = self.getDefaultStorageType()
|
||||
}
|
||||
if diskConf.Size > 0 {
|
||||
if diskConf.SizeMb > 0 {
|
||||
if diskIdx >= len(disks) {
|
||||
newDisks.Add(jsonutils.Marshal(diskConf), fmt.Sprintf("disk.%d", newDiskIdx))
|
||||
newDiskIdx += 1
|
||||
addDisk += diskConf.Size
|
||||
addDisk += diskConf.SizeMb
|
||||
storage := host.GetLeastUsedStorage(diskConf.Backend)
|
||||
if storage == nil {
|
||||
return nil, httperrors.NewResourceNotReadyError("host not connect storage %s", diskConf.Backend)
|
||||
@@ -1206,22 +1206,22 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
if !ok {
|
||||
diskSizes[storage.Id] = 0
|
||||
}
|
||||
diskSizes[storage.Id] = diskSizes[storage.Id] + diskConf.Size
|
||||
diskSizes[storage.Id] = diskSizes[storage.Id] + diskConf.SizeMb
|
||||
} else {
|
||||
disk := disks[diskIdx].GetDisk()
|
||||
oldSize := disk.DiskSize
|
||||
if diskConf.Size < oldSize {
|
||||
if diskConf.SizeMb < oldSize {
|
||||
return nil, httperrors.NewInputParameterError("Cannot reduce disk size")
|
||||
} else if diskConf.Size > oldSize {
|
||||
arr := jsonutils.NewArray(jsonutils.NewString(disks[diskIdx].DiskId), jsonutils.NewInt(int64(diskConf.Size)))
|
||||
} else if diskConf.SizeMb > oldSize {
|
||||
arr := jsonutils.NewArray(jsonutils.NewString(disks[diskIdx].DiskId), jsonutils.NewInt(int64(diskConf.SizeMb)))
|
||||
resizeDisks.Add(arr)
|
||||
addDisk += diskConf.Size - oldSize
|
||||
addDisk += diskConf.SizeMb - oldSize
|
||||
storage := disks[diskIdx].GetDisk().GetStorage()
|
||||
_, ok := diskSizes[storage.Id]
|
||||
if !ok {
|
||||
diskSizes[storage.Id] = 0
|
||||
}
|
||||
diskSizes[storage.Id] = diskSizes[storage.Id] + diskConf.Size - oldSize
|
||||
diskSizes[storage.Id] = diskSizes[storage.Id] + diskConf.SizeMb - oldSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,7 +822,7 @@ func getGuestResourceRequirements(ctx context.Context, userCred mcclient.TokenCr
|
||||
for idx := 0; data.Contains(fmt.Sprintf("disk.%d", idx)); idx += 1 {
|
||||
dataJson, _ := data.Get(fmt.Sprintf("disk.%d", idx))
|
||||
diskConfig, _ := parseDiskInfo(ctx, userCred, dataJson)
|
||||
diskSize += diskConfig.Size
|
||||
diskSize += diskConfig.SizeMb
|
||||
}
|
||||
|
||||
devCount := 0
|
||||
|
||||
@@ -14,6 +14,7 @@ type IHostDriver interface {
|
||||
GetHostType() string
|
||||
CheckAndSetCacheImage(ctx context.Context, host *SHost, storagecache *SStoragecache, task taskman.ITask) error
|
||||
ValidateUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
ValidateDiskSize(storage *SStorage, sizeGb int) error
|
||||
RequestPrepareSaveDiskOnHost(ctx context.Context, host *SHost, disk *SDisk, imageId string, task taskman.ITask) error
|
||||
RequestSaveUploadImageOnHost(ctx context.Context, host *SHost, disk *SDisk, imageId string, task taskman.ITask, data jsonutils.JSONObject) error
|
||||
RequestAllocateDiskOnStorage(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, task taskman.ITask, content *jsonutils.JSONDict) error
|
||||
|
||||
Reference in New Issue
Block a user