From aa5cbd0b0e3bdb1bb8b9962c04fe52ddbc1250d8 Mon Sep 17 00:00:00 2001 From: Qu Xuan Date: Mon, 16 Nov 2020 18:11:56 +0800 Subject: [PATCH] optimized: aliyun create rds backup --- pkg/compute/regiondrivers/aliyun.go | 31 ----------- pkg/multicloud/aliyun/dbinstance_backup.go | 52 ++++++++++++++----- .../aliyun/shell/dbinstance_backup.go | 16 ++++++ 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/pkg/compute/regiondrivers/aliyun.go b/pkg/compute/regiondrivers/aliyun.go index ca1fb2bc2f..37019f0547 100644 --- a/pkg/compute/regiondrivers/aliyun.go +++ b/pkg/compute/regiondrivers/aliyun.go @@ -1100,37 +1100,6 @@ func (self *SAliyunRegionDriver) IsSupportedBillingCycle(bc billing.SBillingCycl return false } -func (self *SAliyunRegionDriver) RequestCreateDBInstanceBackup(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, backup *models.SDBInstanceBackup, task taskman.ITask) error { - taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - iRds, err := instance.GetIDBInstance() - if err != nil { - return nil, errors.Wrap(err, "instance.GetIDBInstance") - } - - desc := &cloudprovider.SDBInstanceBackupCreateConfig{ - Name: backup.Name, - } - if len(backup.DBNames) > 0 { - desc.Databases = strings.Split(backup.DBNames, ",") - } - - _, err = iRds.CreateIBackup(desc) - if err != nil { - return nil, errors.Wrap(err, "iRds.CreateBackup") - } - - backups, err := iRds.GetIDBInstanceBackups() - if err != nil { - return nil, errors.Wrap(err, "iRds.GetIDBInstanceBackups") - } - result := models.DBInstanceBackupManager.SyncDBInstanceBackups(ctx, userCred, backup.GetCloudprovider(), instance, backup.GetRegion(), backups) - log.Infof("SyncDBInstanceBackups for dbinstance %s(%s) result: %s", instance.Name, instance.Id, result.Result()) - instance.SetStatus(userCred, api.DBINSTANCE_RUNNING, "") - return nil, nil - }) - return nil -} - func (self *SAliyunRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) { if len(input.Name) < 2 || len(input.Name) > 16 { return input, httperrors.NewInputParameterError("Aliyun DBInstance account name length shoud be 2~16 characters") diff --git a/pkg/multicloud/aliyun/dbinstance_backup.go b/pkg/multicloud/aliyun/dbinstance_backup.go index 1bf84ce4dc..b548cb4785 100644 --- a/pkg/multicloud/aliyun/dbinstance_backup.go +++ b/pkg/multicloud/aliyun/dbinstance_backup.go @@ -184,9 +184,13 @@ func (rds *SDBInstance) GetIDBInstanceBackups() ([]cloudprovider.ICloudDBInstanc return ibackups, nil } -func (rds *SDBInstance) CreateIBackup(conf *cloudprovider.SDBInstanceBackupCreateConfig) (string, error) { +func (self *SRegion) CreateDBInstanceBackup(rdsId string, databases []string) (string, error) { + rds, err := self.GetDBInstanceDetail(rdsId) + if err != nil { + return "", errors.Wrapf(err, "GetDBInstanceDetail") + } params := map[string]string{ - "DBInstanceId": rds.DBInstanceId, + "DBInstanceId": rdsId, } switch rds.Engine { case api.DBINSTANCE_TYPE_MYSQL: @@ -199,9 +203,9 @@ func (rds *SDBInstance) CreateIBackup(conf *cloudprovider.SDBInstanceBackupCreat params["BackupMethod"] = "Snapshot" } else { params["BackupMethod"] = "Physical" - if len(conf.Databases) > 0 { + if len(databases) > 0 { params["BackupStrategy"] = "db" - params["DBName"] = strings.Join(conf.Databases, ",") + params["DBName"] = strings.Join(databases, ",") params["BackupMethod"] = "Logical" } } @@ -218,7 +222,7 @@ func (rds *SDBInstance) CreateIBackup(conf *cloudprovider.SDBInstanceBackupCreat case api.DBINSTANCE_TYPE_PPAS: params["BackupMethod"] = "Physical" } - body, err := rds.region.rdsRequest("CreateBackup", params) + body, err := self.rdsRequest("CreateBackup", params) if err != nil { return "", errors.Wrap(err, "CreateBackup") } @@ -226,7 +230,11 @@ func (rds *SDBInstance) CreateIBackup(conf *cloudprovider.SDBInstanceBackupCreat if err != nil { return "", errors.Wrap(err, "body.BackupJobId") } - return "", rds.region.waitBackupCreateComplete(rds.DBInstanceId, jobId) + return self.waitBackupCreateComplete(rds.DBInstanceId, jobId) +} + +func (rds *SDBInstance) CreateIBackup(conf *cloudprovider.SDBInstanceBackupCreateConfig) (string, error) { + return rds.region.CreateDBInstanceBackup(rds.DBInstanceId, conf.Databases) } func (backup *SDBInstanceBackup) Delete() error { @@ -249,6 +257,7 @@ type SDBInstanceBackupJob struct { TaskAction string BackupStatus string BackupJobId string + BackupId string } type SDBInstanceBackupJobs struct { @@ -279,25 +288,40 @@ func (region *SRegion) GetDBInstanceBackupJobs(instanceId, jobId string) (*SDBIn return &jobs, nil } -func (region *SRegion) waitBackupCreateComplete(instanceId, jobId string) error { - for i := 0; i < 20*40; i++ { +func (region *SRegion) waitBackupCreateComplete(instanceId, jobId string) (string, error) { + err := cloudprovider.Wait(time.Second*10, time.Minute*40, func() (bool, error) { jobs, err := region.GetDBInstanceBackupJobs(instanceId, jobId) if err != nil { - return errors.Wrapf(err, "region.GetDBInstanceBackupJobs(%s, %s)", instanceId, jobId) + return false, errors.Wrapf(err, "region.GetDBInstanceBackupJobs(%s, %s)", instanceId, jobId) } if len(jobs.BackupJob) == 0 { - return nil + return true, nil } for _, job := range jobs.BackupJob { log.Infof("instance %s backup job %s status: %s(%s)", instanceId, jobId, job.BackupStatus, job.Process) if job.BackupStatus == "Finished" && job.BackupJobId == jobId { - return nil + return true, nil } if job.BackupStatus == "Failed" && job.BackupJobId == jobId { - return fmt.Errorf("instance %s backup job %s failed", instanceId, jobId) + return false, fmt.Errorf("instance %s backup job %s failed", instanceId, jobId) } } - time.Sleep(time.Second * 3) + return false, nil + }) + if err != nil { + return "", errors.Wrapf(err, "wait backup create job") } - return fmt.Errorf("timeout for waiting create job complete") + jobs, err := region.GetDBInstanceBackupJobs(instanceId, jobId) + if err != nil { + return "", errors.Wrapf(err, "region.GetDBInstanceBackupJobs(%s, %s)", instanceId, jobId) + } + for _, job := range jobs.BackupJob { + if job.BackupStatus == "Finished" && job.BackupJobId == jobId { + if len(job.BackupId) == 0 { + return "", fmt.Errorf("Missing backup id") + } + return job.BackupId, nil + } + } + return "", fmt.Errorf("failed to found backup job %s backupid", jobId) } diff --git a/pkg/multicloud/aliyun/shell/dbinstance_backup.go b/pkg/multicloud/aliyun/shell/dbinstance_backup.go index 848e6f41ce..f81521d106 100644 --- a/pkg/multicloud/aliyun/shell/dbinstance_backup.go +++ b/pkg/multicloud/aliyun/shell/dbinstance_backup.go @@ -15,6 +15,8 @@ package shell import ( + "fmt" + "yunion.io/x/onecloud/pkg/multicloud/aliyun" "yunion.io/x/onecloud/pkg/util/shellutils" ) @@ -61,4 +63,18 @@ func init() { return nil }) + type DBInstanceBackupCreateOptions struct { + INSTANCE_ID string + Database []string + } + + shellutils.R(&DBInstanceBackupCreateOptions{}, "dbinstance-backup-create", "Create dbintance backup", func(cli *aliyun.SRegion, args *DBInstanceBackupCreateOptions) error { + backupId, err := cli.CreateDBInstanceBackup(args.INSTANCE_ID, args.Database) + if err != nil { + return err + } + fmt.Println("backup id: ", backupId) + return nil + }) + }