diff --git a/pkg/cloudprovider/resources.go b/pkg/cloudprovider/resources.go index 83fe90abfd..25402183df 100644 --- a/pkg/cloudprovider/resources.go +++ b/pkg/cloudprovider/resources.go @@ -189,6 +189,7 @@ type ICloudDisk interface { GetCacheMode() string GetMountpoint() string Delete() error + Resize(int64) error } type ICloudVpc interface { diff --git a/pkg/compute/hostdrivers/aliyun.go b/pkg/compute/hostdrivers/aliyun.go index 71522887a3..0bcfa18005 100644 --- a/pkg/compute/hostdrivers/aliyun.go +++ b/pkg/compute/hostdrivers/aliyun.go @@ -4,6 +4,7 @@ import ( "context" "yunion.io/x/jsonutils" + "yunion.io/x/log" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/compute/models" ) @@ -55,12 +56,19 @@ func (self *SAliyunHostDriver) RequestAllocateDiskOnStorage(host *models.SHost, return err } else { size = size >> 10 - if disk, err := iCloudStorage.CreateIDisk(disk.GetName(), int(size), ""); err != nil { + if iDisk, err := iCloudStorage.CreateIDisk(disk.GetName(), int(size), ""); err != nil { return err } else { + if _, err := disk.GetModelManager().TableSpec().Update(disk, func() error { + disk.ExternalId = iDisk.GetGlobalId() + return nil + }); err != nil { + log.Errorf("Update disk externalId err: %v", err) + return err + } data := jsonutils.NewDict() - data.Add(jsonutils.NewInt(int64(disk.GetDiskSizeMB())), "disk_size") - data.Add(jsonutils.NewString(disk.GetDiskFormat()), "disk_format") + data.Add(jsonutils.NewInt(int64(iDisk.GetDiskSizeMB())), "disk_size") + data.Add(jsonutils.NewString(iDisk.GetDiskFormat()), "disk_format") task.ScheduleRun(data) } } @@ -79,8 +87,18 @@ func (self *SAliyunHostDriver) RequestDeallocateDiskOnHost(host *models.SHost, s } func (self *SAliyunHostDriver) RequestResizeDiskOnHostOnline(host *models.SHost, storage *models.SStorage, disk *models.SDisk, size int64, task taskman.ITask) error { - return nil + return self.RequestResizeDiskOnHost(host, storage, disk, size, task) } + func (self *SAliyunHostDriver) RequestResizeDiskOnHost(host *models.SHost, storage *models.SStorage, disk *models.SDisk, size int64, task taskman.ITask) error { + if iCloudStorage, err := storage.GetIStorage(); err != nil { + return err + } else if iDisk, err := iCloudStorage.GetIDisk(disk.GetExternalId()); err != nil { + return err + } else if err := iDisk.Resize(size >> 10); err != nil { + return err + } else { + task.ScheduleRun(jsonutils.Marshal(map[string]int64{"disk_size": size})) + } return nil } diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 7b18930843..17f1e23bc4 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -259,7 +259,7 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc if len(hoststorage) == 0 { return nil, httperrors.NewInputParameterError("Storage[%s] must attach to a host", storage.Name) } - if diskConfig.Size > storage.GetFreeCapacity() { + if diskConfig.Size > storage.GetFreeCapacity() && !storage.IsEmulated { return nil, httperrors.NewInputParameterError("Not enough free space") } if _, err := manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data); err != nil { @@ -346,7 +346,7 @@ func (self *SDisk) PerformResize(ctx context.Context, userCred mcclient.TokenCre } else { addDisk := size - self.DiskSize storage := self.GetStorage() - if addDisk > storage.GetFreeCapacity() { + if addDisk > storage.GetFreeCapacity() && !storage.IsEmulated { return nil, httperrors.NewOutOfResourceError("Not enough free space") } pendingUsage := SQuota{Storage: int(addDisk)} diff --git a/pkg/compute/tasks/disk_create_task.go b/pkg/compute/tasks/disk_create_task.go index 35b6c035f1..46383e7a83 100644 --- a/pkg/compute/tasks/disk_create_task.go +++ b/pkg/compute/tasks/disk_create_task.go @@ -4,6 +4,7 @@ import ( "context" "yunion.io/x/jsonutils" + "yunion.io/x/log" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" @@ -54,9 +55,15 @@ func (self *DiskCreateTask) OnStartAllocateFailed(ctx context.Context, disk *mod func (self *DiskCreateTask) OnDiskReady(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) { diskSize, _ := data.Int("disk_size") - disk.DiskSize = int(diskSize) - disk.DiskFormat, _ = data.GetString("disk_format") - disk.AccessPath, _ = data.GetString("disk_path") + if _, err := disk.GetModelManager().TableSpec().Update(disk, func() error { + disk.DiskSize = int(diskSize) + disk.DiskFormat, _ = data.GetString("disk_format") + disk.AccessPath, _ = data.GetString("disk_path") + return nil + }); err != nil { + log.Errorf("update disk info error: %v", err) + } + disk.SetStatus(self.UserCred, models.DISK_READY, "") self.CleanHostSchedCache(disk) db.OpsLog.LogEvent(disk, db.ACT_ALLOCATE, disk.GetShortDesc(), self.UserCred) diff --git a/pkg/compute/tasks/disk_resize_task.go b/pkg/compute/tasks/disk_resize_task.go index f1cddaaf83..584c43ab94 100644 --- a/pkg/compute/tasks/disk_resize_task.go +++ b/pkg/compute/tasks/disk_resize_task.go @@ -54,7 +54,7 @@ func (self *DiskResizeTask) StartResizeDisk(ctx context.Context, host *models.SH } if err := proc(host, storage, disk, size, self); err != nil { log.Errorf("request_resize_disk_on_host: %v", err) - self.OnStartResizeDiskFailed(ctx, err) + self.OnStartResizeDiskFailed(ctx, disk, err) return } self.OnStartResizeDiskSucc(ctx, disk) @@ -64,8 +64,7 @@ func (self *DiskResizeTask) OnStartResizeDiskSucc(ctx context.Context, disk *mod disk.SetStatus(self.GetUserCred(), models.DISK_RESIZING, "") } -func (self *DiskResizeTask) OnStartResizeDiskFailed(ctx context.Context, resion error) { - disk := self.getDisk() +func (self *DiskResizeTask) OnStartResizeDiskFailed(ctx context.Context, disk *models.SDisk, resion error) { disk.SetStatus(self.GetUserCred(), models.DISK_READY, resion.Error()) self.SetStageFailed(ctx, resion.Error()) db.OpsLog.LogEvent(disk, db.ACT_RESIZE_FAIL, resion.Error(), self.GetUserCred()) @@ -75,13 +74,13 @@ func (self *DiskResizeTask) OnDiskResizeComplete(ctx context.Context, disk *mode jSize, err := data.Get("disk_size") if err != nil { log.Errorf("OnDiskResizeComplete error: %s", err.Error()) - self.OnStartResizeDiskFailed(ctx, err) + self.OnStartResizeDiskFailed(ctx, disk, err) return } size, err := jSize.Int() if err != nil { log.Errorf("OnDiskResizeComplete error: %s", err.Error()) - self.OnStartResizeDiskFailed(ctx, err) + self.OnStartResizeDiskFailed(ctx, disk, err) return } oldStatus := disk.Status @@ -92,7 +91,7 @@ func (self *DiskResizeTask) OnDiskResizeComplete(ctx context.Context, disk *mode }) if err != nil { log.Errorf("OnDiskResizeComplete error: %s", err.Error()) - self.OnStartResizeDiskFailed(ctx, err) + self.OnStartResizeDiskFailed(ctx, disk, err) return } notes := fmt.Sprintf("%s=>%s", oldStatus, disk.Status) diff --git a/pkg/util/aliyun/disk.go b/pkg/util/aliyun/disk.go index 0512e1899b..aeeca8096c 100644 --- a/pkg/util/aliyun/disk.go +++ b/pkg/util/aliyun/disk.go @@ -100,6 +100,10 @@ func (self *SDisk) Delete() error { return self.storage.zone.region.deleteDisk(self.DiskId) } +func (self *SDisk) Resize(size int64) error { + return self.storage.zone.region.resizeDisk(self.DiskId, size) +} + func (self *SDisk) GetName() string { return self.DiskId } @@ -218,3 +222,12 @@ func (self *SRegion) deleteDisk(diskId string) error { _, err := self.ecsRequest("DeleteDisk", params) return err } + +func (self *SRegion) resizeDisk(diskId string, size int64) error { + params := make(map[string]string) + params["DiskId"] = diskId + params["NewSize"] = fmt.Sprintf("%d", size) + + _, err := self.ecsRequest("ResizeDisk", params) + return err +}