From dd55eae07727cb94b20607d88cafaff37b2fe82f Mon Sep 17 00:00:00 2001 From: Qu Xuan Date: Mon, 15 Mar 2021 16:03:29 +0800 Subject: [PATCH] fix: change rds config skip zone check --- pkg/apis/compute/dbinstance.go | 4 - pkg/cloudprovider/dbinstance.go | 3 - pkg/compute/models/dbinstances.go | 69 ++----------- pkg/compute/models/regiondrivers.go | 3 +- pkg/compute/regiondrivers/base.go | 6 +- pkg/compute/regiondrivers/huawei.go | 6 -- pkg/compute/regiondrivers/managedvirtual.go | 97 +++++-------------- pkg/compute/tasks/dbinstance_change_config.go | 14 ++- pkg/multicloud/aliyun/dbinstance.go | 14 ++- pkg/multicloud/huawei/dbinstance.go | 8 -- pkg/multicloud/qcloud/rds_mysql.go | 23 ++++- 11 files changed, 75 insertions(+), 172 deletions(-) diff --git a/pkg/apis/compute/dbinstance.go b/pkg/apis/compute/dbinstance.go index ed2ecd3657..e956a6421e 100644 --- a/pkg/apis/compute/dbinstance.go +++ b/pkg/apis/compute/dbinstance.go @@ -166,11 +166,7 @@ type SDBInstanceChangeConfigInput struct { apis.Meta InstanceType string - VCpuCount int - VmemSizeMb int - StorageType string DiskSizeGB int - Category string } type SDBInstanceRecoveryConfigInput struct { diff --git a/pkg/cloudprovider/dbinstance.go b/pkg/cloudprovider/dbinstance.go index e1b3cb7363..82a2a989f5 100644 --- a/pkg/cloudprovider/dbinstance.go +++ b/pkg/cloudprovider/dbinstance.go @@ -77,10 +77,7 @@ type SManagedDBInstanceCreateConfig struct { type SManagedDBInstanceChangeConfig struct { DiskSizeGB int - StorageType string InstanceType string - VcpuCount int - VmemSizeMb int } type SDBInstanceDatabaseCreateConfig struct { diff --git a/pkg/compute/models/dbinstances.go b/pkg/compute/models/dbinstances.go index bd09817c27..e9d446996e 100644 --- a/pkg/compute/models/dbinstances.go +++ b/pkg/compute/models/dbinstances.go @@ -1062,57 +1062,20 @@ func (self *SDBInstance) AllowPerformChangeConfig(ctx context.Context, userCred return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "change-config") } -func (self *SDBInstance) PerformChangeConfig(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { +func (self *SDBInstance) PerformChangeConfig(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SDBInstanceChangeConfigInput) (jsonutils.JSONObject, error) { if !utils.IsInStringArray(self.Status, []string{api.DBINSTANCE_RUNNING}) { return nil, httperrors.NewInputParameterError("Cannot change config in status %s", self.Status) } - input := api.SDBInstanceChangeConfigInput{} - err := data.Unmarshal(&input) - if err != nil { - return nil, httperrors.NewInputParameterError("Unmarshal input error: %v", err) + + if input.DiskSizeGB != 0 && input.DiskSizeGB < self.DiskSizeGB { + return nil, httperrors.NewUnsupportOperationError("DBInstance Disk cannot be thrink") } - tmp := &SDBInstance{} - jsonutils.Update(tmp, self) - - if len(input.StorageType) > 0 { - self.StorageType = input.StorageType + if input.DiskSizeGB == self.DiskSizeGB && input.InstanceType == self.InstanceType { + return nil, nil } - changed := false - if len(input.InstanceType) > 0 { - tmp.InstanceType = input.InstanceType - changed = true - } else if input.VCpuCount > 0 { - tmp.VcpuCount = input.VCpuCount - self.InstanceType = "" - changed = true - } else if input.VmemSizeMb > 0 { - tmp.VmemSizeMb = input.VmemSizeMb - tmp.InstanceType = "" - changed = true - } else if len(input.Category) > 0 { - tmp.Category = input.Category - tmp.InstanceType = "" - changed = true - } - - if changed { - skus, err := tmp.GetAvailableDBInstanceSkus(true) - if err != nil { - return nil, httperrors.NewGeneralError(errors.Wrap(err, "self.GetAvailableDBInstanceSkus")) - } - if len(skus) == 0 { - return nil, httperrors.NewInputParameterError("failed to match any skus for change config") - } - } - - err = self.GetRegion().GetDriver().ValidateChangeDBInstanceConfigData(ctx, userCred, self, &input) - if err != nil { - return nil, err - } - - return nil, self.StartDBInstanceChangeConfig(ctx, userCred, data.(*jsonutils.JSONDict), "") + return nil, self.StartDBInstanceChangeConfig(ctx, userCred, jsonutils.Marshal(input).(*jsonutils.JSONDict), "") } func (self *SDBInstance) StartDBInstanceChangeConfig(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error { @@ -1542,9 +1505,9 @@ func (self *SDBInstance) GetAvailableDBInstanceSkus(skipZoneCheck bool) ([]SDBIn } -func (self *SDBInstance) GetDBInstanceSkus() ([]SDBInstanceSku, error) { +func (self *SDBInstance) GetDBInstanceSkus(skipZoneCheck bool) ([]SDBInstanceSku, error) { skus := []SDBInstanceSku{} - q := self.GetDBInstanceSkuQuery(false) + q := self.GetDBInstanceSkuQuery(skipZoneCheck) err := db.FetchModelObjects(DBInstanceSkuManager, q, &skus) if err != nil { return nil, err @@ -1552,20 +1515,6 @@ func (self *SDBInstance) GetDBInstanceSkus() ([]SDBInstanceSku, error) { return skus, nil } -func (self *SDBInstance) GetAvailableZoneIds() ([]string, error) { - zoneIds := []string{} - skus, err := self.GetDBInstanceSkus() - if err != nil { - return nil, errors.Wrap(err, "self.GetDBInstanceSkus") - } - for _, sku := range skus { - if !utils.IsInStringArray(sku.ZoneId, zoneIds) { - zoneIds = append(zoneIds, sku.ZoneId) - } - } - return zoneIds, nil -} - func (self *SDBInstance) GetAvailableInstanceTypes() ([]cloudprovider.SInstanceType, error) { instanceTypes := []cloudprovider.SInstanceType{} skus, err := self.GetAvailableDBInstanceSkus(false) diff --git a/pkg/compute/models/regiondrivers.go b/pkg/compute/models/regiondrivers.go index 2525139143..e07b2ddf90 100644 --- a/pkg/compute/models/regiondrivers.go +++ b/pkg/compute/models/regiondrivers.go @@ -158,14 +158,13 @@ type IDBInstanceDriver interface { ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input api.DBInstanceDatabaseCreateInput) (api.DBInstanceDatabaseCreateInput, error) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input api.DBInstanceBackupCreateInput) (api.DBInstanceBackupCreateInput, error) - ValidateChangeDBInstanceConfigData(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, input *api.SDBInstanceChangeConfigInput) error ValidateDBInstanceAccountPrivilege(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, account string, privilege string) error ValidateResetDBInstancePassword(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, account string) error RequestCreateDBInstance(ctx context.Context, userCred mcclient.TokenCredential, dbinstance *SDBInstance, task taskman.ITask) error RequestCreateDBInstanceFromBackup(ctx context.Context, userCred mcclient.TokenCredential, dbinstance *SDBInstance, task taskman.ITask) error RequestCreateDBInstanceBackup(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, backup *SDBInstanceBackup, task taskman.ITask) error - RequestChangeDBInstanceConfig(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, task taskman.ITask) error + RequestChangeDBInstanceConfig(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, input *api.SDBInstanceChangeConfigInput, task taskman.ITask) error IsSupportedDBInstance() bool IsSupportedDBInstanceAutoRenew() bool diff --git a/pkg/compute/regiondrivers/base.go b/pkg/compute/regiondrivers/base.go index 8b470e7875..e1f8b18849 100644 --- a/pkg/compute/regiondrivers/base.go +++ b/pkg/compute/regiondrivers/base.go @@ -316,7 +316,7 @@ func (self *SBaseRegionDriver) InitDBInstanceUser(ctx context.Context, dbinstanc return nil } -func (self *SBaseRegionDriver) RequestChangeDBInstanceConfig(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, task taskman.ITask) error { +func (self *SBaseRegionDriver) RequestChangeDBInstanceConfig(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, input *api.SDBInstanceChangeConfigInput, task taskman.ITask) error { return fmt.Errorf("Not Implement RequestChangeDBInstanceConfig") } @@ -332,10 +332,6 @@ func (self *SBaseRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Co return input, fmt.Errorf("Not Implement ValidateCreateDBInstanceBackupData") } -func (self *SBaseRegionDriver) ValidateChangeDBInstanceConfigData(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, input *api.SDBInstanceChangeConfigInput) error { - return fmt.Errorf("Not Implement ValidateChangeDBInstanceConfigData") -} - func (self *SBaseRegionDriver) ValidateDBInstanceAccountPrivilege(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, account string, privilege string) error { return fmt.Errorf("Not Implement ValidateDBInstanceAccountPrivilege") } diff --git a/pkg/compute/regiondrivers/huawei.go b/pkg/compute/regiondrivers/huawei.go index 29ab0b2c6f..a66e2c2578 100644 --- a/pkg/compute/regiondrivers/huawei.go +++ b/pkg/compute/regiondrivers/huawei.go @@ -2232,12 +2232,6 @@ func (self *SHuaWeiRegionDriver) ValidateChangeDBInstanceConfigData(ctx context. if input.DiskSizeGB != 0 && input.DiskSizeGB < instance.DiskSizeGB { return httperrors.NewUnsupportOperationError("Huawei DBInstance Disk cannot be thrink") } - if len(input.Category) > 0 && input.Category != instance.Category { - return httperrors.NewUnsupportOperationError("Huawei DBInstance category cannot change") - } - if len(input.StorageType) > 0 && input.StorageType != instance.StorageType { - return httperrors.NewUnsupportOperationError("Huawei DBInstance storage type cannot change") - } return nil } diff --git a/pkg/compute/regiondrivers/managedvirtual.go b/pkg/compute/regiondrivers/managedvirtual.go index fa3512ce3c..3ee20b8579 100644 --- a/pkg/compute/regiondrivers/managedvirtual.go +++ b/pkg/compute/regiondrivers/managedvirtual.go @@ -2464,74 +2464,27 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcacheAcl(ctx return nil } -func (self *SManagedVirtualizationRegionDriver) RequestChangeDBInstanceConfig(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, task taskman.ITask) error { +func (self *SManagedVirtualizationRegionDriver) RequestChangeDBInstanceConfig(ctx context.Context, userCred mcclient.TokenCredential, rds *models.SDBInstance, input *api.SDBInstanceChangeConfigInput, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - input := &api.SDBInstanceChangeConfigInput{} - err := task.GetParams().Unmarshal(input) + conf := cloudprovider.SManagedDBInstanceChangeConfig{} + + if input.DiskSizeGB > 0 && input.DiskSizeGB != rds.DiskSizeGB { + conf.DiskSizeGB = input.DiskSizeGB + } + + if len(input.InstanceType) > 0 && input.InstanceType != rds.InstanceType { + conf.InstanceType = input.InstanceType + } + + iRds, err := rds.GetIDBInstance() if err != nil { - return nil, errors.Wrap(err, "task.GetParams().Unmarshal") - } - if len(input.StorageType) > 0 { - instance.StorageType = input.StorageType + return nil, errors.Wrap(err, "rds.GetIDBInstance") } - conf := cloudprovider.SManagedDBInstanceChangeConfig{ - DiskSizeGB: input.DiskSizeGB, - StorageType: instance.StorageType, - } - - opts := []cloudprovider.SManagedDBInstanceChangeConfig{} - - if len(input.InstanceType) > 0 || input.VCpuCount > 0 || input.VmemSizeMb > 0 { - instance.InstanceType = input.InstanceType - if input.VCpuCount > 0 { - instance.VcpuCount = input.VCpuCount - } - if input.VmemSizeMb > 0 { - instance.VmemSizeMb = input.VmemSizeMb - } - skus, err := instance.GetDBInstanceSkus() - if err != nil { - return nil, errors.Wrap(err, "instance.GetDBInstanceSkus") - } - for i := range skus { - conf.InstanceType = skus[i].Name - conf.VcpuCount = skus[i].VcpuCount - conf.VmemSizeMb = skus[i].VmemSizeMb - opts = append(opts, conf) - } - } else { - conf.InstanceType = instance.InstanceType - conf.VcpuCount = instance.VcpuCount - conf.VmemSizeMb = instance.VmemSizeMb - opts = append(opts, conf) - } - - iRds, err := instance.GetIDBInstance() + log.Infof("change config: %s", jsonutils.Marshal(conf).String()) + err = iRds.ChangeConfig(ctx, &conf) if err != nil { - return nil, errors.Wrap(err, "instance.GetIDBInstance") - } - - var changeConfig = func() error { - errMsgs := []string{} - for i := range opts { - log.Infof("change config: %s", jsonutils.Marshal(opts[i]).String()) - err = iRds.ChangeConfig(ctx, &opts[i]) - if err != nil { - errMsgs = append(errMsgs, err.Error()) - continue - } - return nil - } - if len(errMsgs) > 0 { - return fmt.Errorf(strings.Join(errMsgs, "\n")) - } - return fmt.Errorf("no available dbinstance sku to change") - } - - err = changeConfig() - if err != nil { - return nil, err + return nil, errors.Wrapf(err, "iRds.ChangeConfig") } err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*10, time.Minute*40) @@ -2544,13 +2497,13 @@ func (self *SManagedVirtualizationRegionDriver) RequestChangeDBInstanceConfig(ct return nil, errors.Wrapf(err, "iRds.Refresh") } - _, err = db.Update(instance, func() error { - instance.InstanceType = iRds.GetInstanceType() - instance.Category = iRds.GetCategory() - instance.VcpuCount = iRds.GetVcpuCount() - instance.VmemSizeMb = iRds.GetVmemSizeMB() - instance.StorageType = iRds.GetStorageType() - instance.DiskSizeGB = iRds.GetDiskSizeGB() + _, err = db.Update(rds, func() error { + rds.InstanceType = iRds.GetInstanceType() + rds.Category = iRds.GetCategory() + rds.VcpuCount = iRds.GetVcpuCount() + rds.VmemSizeMb = iRds.GetVmemSizeMB() + rds.StorageType = iRds.GetStorageType() + rds.DiskSizeGB = iRds.GetDiskSizeGB() return nil }) if err != nil { @@ -2613,10 +2566,6 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceBackup(ct return nil } -func (self *SManagedVirtualizationRegionDriver) ValidateChangeDBInstanceConfigData(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, input *api.SDBInstanceChangeConfigInput) error { - return nil -} - func (self *SManagedVirtualizationRegionDriver) ValidateResetDBInstancePassword(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, account string) error { return nil } diff --git a/pkg/compute/tasks/dbinstance_change_config.go b/pkg/compute/tasks/dbinstance_change_config.go index 8f10a2c55d..3404e08ff8 100644 --- a/pkg/compute/tasks/dbinstance_change_config.go +++ b/pkg/compute/tasks/dbinstance_change_config.go @@ -19,6 +19,7 @@ import ( "fmt" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" @@ -44,11 +45,18 @@ func (self *DBInstanceChangeConfigTask) taskFailed(ctx context.Context, dbinstan } func (self *DBInstanceChangeConfigTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { - instance := obj.(*models.SDBInstance) + rds := obj.(*models.SDBInstance) self.SetStage("OnDBInstanceChangeConfigComplete", nil) - err := instance.GetRegion().GetDriver().RequestChangeDBInstanceConfig(ctx, self.UserCred, instance, self) + input := &api.SDBInstanceChangeConfigInput{} + err := self.GetParams().Unmarshal(input) if err != nil { - self.taskFailed(ctx, instance, err) + self.taskFailed(ctx, rds, errors.Wrapf(err, "GetParams().Unmarshal")) + return + } + + err = rds.GetRegion().GetDriver().RequestChangeDBInstanceConfig(ctx, self.UserCred, rds, input, self) + if err != nil { + self.taskFailed(ctx, rds, err) return } } diff --git a/pkg/multicloud/aliyun/dbinstance.go b/pkg/multicloud/aliyun/dbinstance.go index 047442f331..e2aa0d466c 100644 --- a/pkg/multicloud/aliyun/dbinstance.go +++ b/pkg/multicloud/aliyun/dbinstance.go @@ -630,11 +630,15 @@ func (rds *SDBInstance) ChangeConfig(cxt context.Context, desc *cloudprovider.SM func (region *SRegion) ChangeDBInstanceConfig(instanceId, payType string, desc *cloudprovider.SManagedDBInstanceChangeConfig) error { params := map[string]string{ - "RegionId": region.RegionId, - "DBInstanceId": instanceId, - "PayType": payType, - "DBInstanceClass": desc.InstanceType, - "DBInstanceStorage": fmt.Sprintf("%d", desc.DiskSizeGB), + "RegionId": region.RegionId, + "DBInstanceId": instanceId, + "PayType": payType, + } + if len(desc.InstanceType) > 0 { + params["DBInstanceClass"] = desc.InstanceType + } + if desc.DiskSizeGB > 0 { + params["DBInstanceStorage"] = fmt.Sprintf("%d", desc.DiskSizeGB) } _, err := region.rdsRequest("ModifyDBInstanceSpec", params) diff --git a/pkg/multicloud/huawei/dbinstance.go b/pkg/multicloud/huawei/dbinstance.go index 694d7838cc..cc4f70dca5 100644 --- a/pkg/multicloud/huawei/dbinstance.go +++ b/pkg/multicloud/huawei/dbinstance.go @@ -644,14 +644,6 @@ func (region *SRegion) CreateDBInstanceDatabase(instanceId, database, characterS } func (rds *SDBInstance) ChangeConfig(cxt context.Context, desc *cloudprovider.SManagedDBInstanceChangeConfig) error { - if rds.GetInstanceType() == desc.InstanceType { - desc.InstanceType = "" - } - - if rds.GetDiskSizeGB() >= desc.DiskSizeGB { - desc.DiskSizeGB = 0 - } - return rds.region.ChangeDBInstanceConfig(rds.Id, desc.InstanceType, desc.DiskSizeGB) } diff --git a/pkg/multicloud/qcloud/rds_mysql.go b/pkg/multicloud/qcloud/rds_mysql.go index 4930d38eb8..a90fb6efdb 100644 --- a/pkg/multicloud/qcloud/rds_mysql.go +++ b/pkg/multicloud/qcloud/rds_mysql.go @@ -17,6 +17,8 @@ package qcloud import ( "context" "fmt" + "regexp" + "strconv" "strings" "time" @@ -232,7 +234,20 @@ func (self *SMySQLInstance) Reboot() error { } func (self *SMySQLInstance) ChangeConfig(ctx context.Context, opts *cloudprovider.SManagedDBInstanceChangeConfig) error { - return self.region.UpgradeMySQLDBInstance(self.InstanceId, opts.VmemSizeMb, opts.DiskSizeGB) + mb := self.GetVmemSizeMB() + if len(opts.InstanceType) > 0 { + re := regexp.MustCompile(`(\d{1,4})核(\d{1,20})MB$`) + params := re.FindStringSubmatch(opts.InstanceType) + if len(params) != 3 { + return fmt.Errorf("invalid rds instance type %s", opts.InstanceType) + } + _mb, _ := strconv.Atoi(params[2]) + mb = int(_mb) + } + if opts.DiskSizeGB == 0 { + opts.DiskSizeGB = self.GetDiskSizeGB() + } + return self.region.UpgradeMySQLDBInstance(self.InstanceId, mb, opts.DiskSizeGB) } func (self *SMySQLInstance) GetMasterInstanceId() string { @@ -330,7 +345,11 @@ func (self *SMySQLInstance) GetStatus() string { } func (self *SMySQLInstance) GetCategory() string { - return strings.ToLower(self.DeviceType) + category := strings.ToLower(self.DeviceType) + if category == "universal" { + category = "ha" + } + return category } func (self *SMySQLInstance) GetStorageType() string {