yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/dbinstance_backup.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package apsara 16 17 import ( 18 "fmt" 19 "strings" 20 "time" 21 22 "github.com/coredns/coredns/plugin/pkg/log" 23 24 "yunion.io/x/pkg/errors" 25 "yunion.io/x/pkg/utils" 26 27 api "yunion.io/x/cloudmux/pkg/apis/compute" 28 "yunion.io/x/cloudmux/pkg/cloudprovider" 29 "yunion.io/x/cloudmux/pkg/multicloud" 30 ) 31 32 type SDBInstanceBackup struct { 33 multicloud.SDBInstanceBackupBase 34 ApsaraTags 35 region *SRegion 36 37 BackupDBNames string 38 BackupIntranetDownloadURL string 39 BackupDownloadURL string 40 BackupEndTime time.Time 41 BackupId string 42 BackupLocation string 43 BackupMethod string 44 BackupMode string 45 BackupScale string 46 BackupSize int 47 BackupStartTime time.Time 48 BackupStatus string 49 BackupType string 50 DBInstanceId string 51 HostInstanceID int 52 MetaStatus string 53 StoreStatus string 54 } 55 56 func (backup *SDBInstanceBackup) GetId() string { 57 return backup.BackupId 58 } 59 60 func (backup *SDBInstanceBackup) GetGlobalId() string { 61 return backup.BackupId 62 } 63 64 func (backup *SDBInstanceBackup) GetName() string { 65 return backup.BackupId 66 } 67 68 func (backup *SDBInstanceBackup) GetStartTime() time.Time { 69 return backup.BackupStartTime 70 } 71 72 func (backup *SDBInstanceBackup) GetEndTime() time.Time { 73 return backup.BackupEndTime 74 } 75 76 func (backup *SDBInstanceBackup) GetBackupMode() string { 77 switch backup.BackupMode { 78 case "Manual": 79 return api.BACKUP_MODE_MANUAL 80 default: 81 return api.BACKUP_MODE_AUTOMATED 82 } 83 } 84 85 func (backup *SDBInstanceBackup) GetStatus() string { 86 switch backup.BackupStatus { 87 case "Success": 88 return api.DBINSTANCE_BACKUP_READY 89 case "Failed": 90 return api.DBINSTANCE_BACKUP_FAILED 91 default: 92 return api.DBINSTANCE_BACKUP_UNKNOWN 93 } 94 } 95 96 func (backup *SDBInstanceBackup) GetBackupSizeMb() int { 97 return backup.BackupSize / 1024 / 1024 98 } 99 100 func (backup *SDBInstanceBackup) GetDBNames() string { 101 return backup.BackupDBNames 102 } 103 104 func (backup *SDBInstanceBackup) GetEngine() string { 105 instance, _ := backup.region.GetDBInstanceDetail(backup.DBInstanceId) 106 if instance != nil { 107 return instance.Engine 108 } 109 return "" 110 } 111 112 func (backup *SDBInstanceBackup) GetEngineVersion() string { 113 instance, _ := backup.region.GetDBInstanceDetail(backup.DBInstanceId) 114 if instance != nil { 115 return instance.EngineVersion 116 } 117 return "" 118 } 119 120 func (backup *SDBInstanceBackup) GetDBInstanceId() string { 121 return backup.DBInstanceId 122 } 123 124 func (region *SRegion) GetDBInstanceBackups(instanceId, backupId string, offset int, limit int) ([]SDBInstanceBackup, int, error) { 125 if limit > 50 || limit <= 0 { 126 limit = 50 127 } 128 params := map[string]string{ 129 "RegionId": region.RegionId, 130 "PageSize": fmt.Sprintf("%d", limit), 131 "PageNumber": fmt.Sprintf("%d", (offset/limit)+1), 132 "DBInstanceId": instanceId, 133 } 134 if len(backupId) > 0 { 135 params["BackupId"] = backupId 136 } 137 body, err := region.rdsRequest("DescribeBackups", params) 138 if err != nil { 139 return nil, 0, errors.Wrap(err, "DescribeBackups") 140 } 141 backups := []SDBInstanceBackup{} 142 err = body.Unmarshal(&backups, "Items", "Backup") 143 if err != nil { 144 return nil, 0, errors.Wrap(err, "Unmarshal") 145 } 146 total, _ := body.Int("TotalRecordCount") 147 return backups, int(total), nil 148 } 149 150 func (region *SRegion) GetIDBInstanceBackups() ([]cloudprovider.ICloudDBInstanceBackup, error) { 151 dbinstnaces, err := region.GetIDBInstances() 152 if err != nil { 153 return nil, err 154 } 155 ibackups := []cloudprovider.ICloudDBInstanceBackup{} 156 for i := 0; i < len(dbinstnaces); i++ { 157 _dbinstance := dbinstnaces[i].(*SDBInstance) 158 _ibackup, err := _dbinstance.GetIDBInstanceBackups() 159 if err != nil { 160 return nil, errors.Wrapf(err, "_dbinstance(%v).GetIDBInstanceBackups", _dbinstance) 161 } 162 ibackups = append(ibackups, _ibackup...) 163 } 164 return ibackups, nil 165 } 166 167 func (rds *SDBInstance) GetIDBInstanceBackups() ([]cloudprovider.ICloudDBInstanceBackup, error) { 168 backups := []SDBInstanceBackup{} 169 for { 170 parts, total, err := rds.region.GetDBInstanceBackups(rds.DBInstanceId, "", len(backups), 50) 171 if err != nil { 172 return nil, err 173 } 174 backups = append(backups, parts...) 175 if len(backups) >= total { 176 break 177 } 178 } 179 180 ibackups := []cloudprovider.ICloudDBInstanceBackup{} 181 for i := 0; i < len(backups); i++ { 182 backups[i].region = rds.region 183 ibackups = append(ibackups, &backups[i]) 184 } 185 return ibackups, nil 186 } 187 188 func (rds *SDBInstance) CreateIBackup(conf *cloudprovider.SDBInstanceBackupCreateConfig) (string, error) { 189 params := map[string]string{ 190 "DBInstanceId": rds.DBInstanceId, 191 } 192 switch rds.Engine { 193 case api.DBINSTANCE_TYPE_MYSQL: 194 if utils.IsInStringArray(rds.EngineVersion, []string{"5.7", "8.0"}) && ((utils.IsInStringArray(rds.GetStorageType(), []string{ 195 api.ALIYUN_DBINSTANCE_STORAGE_TYPE_CLOUD_ESSD, 196 api.ALIYUN_DBINSTANCE_STORAGE_TYPE_CLOUD_SSD, 197 }) && rds.GetCategory() == api.ALIYUN_DBINSTANCE_CATEGORY_HA) || 198 (rds.GetStorageType() == api.ALIYUN_DBINSTANCE_STORAGE_TYPE_CLOUD_SSD && 199 rds.GetCategory() == api.ALIYUN_DBINSTANCE_CATEGORY_BASIC)) { 200 params["BackupMethod"] = "Snapshot" 201 } else { 202 params["BackupMethod"] = "Physical" 203 if len(conf.Databases) > 0 { 204 params["BackupStrategy"] = "db" 205 params["DBName"] = strings.Join(conf.Databases, ",") 206 params["BackupMethod"] = "Logical" 207 } 208 } 209 case api.DBINSTANCE_TYPE_MARIADB: 210 params["BackupMethod"] = "Snapshot" 211 case api.DBINSTANCE_TYPE_SQLSERVER: 212 params["BackupMethod"] = "Physical" 213 case api.DBINSTANCE_TYPE_POSTGRESQL: 214 if rds.GetStorageType() == api.ALIYUN_DBINSTANCE_STORAGE_TYPE_LOCAL_SSD { 215 params["BackupMethod"] = "Physical" 216 } else { 217 params["BackupMethod"] = "Snapshot" 218 } 219 case api.DBINSTANCE_TYPE_PPAS: 220 params["BackupMethod"] = "Physical" 221 } 222 body, err := rds.region.rdsRequest("CreateBackup", params) 223 if err != nil { 224 return "", errors.Wrap(err, "CreateBackup") 225 } 226 jobId, err := body.GetString("BackupJobId") 227 if err != nil { 228 return "", errors.Wrap(err, "body.BackupJobId") 229 } 230 return "", rds.region.waitBackupCreateComplete(rds.DBInstanceId, jobId) 231 } 232 233 func (backup *SDBInstanceBackup) Delete() error { 234 return backup.region.DeleteDBInstanceBackup(backup.DBInstanceId, backup.BackupId) 235 } 236 237 func (region *SRegion) DeleteDBInstanceBackup(instanceId string, backupId string) error { 238 params := map[string]string{ 239 "DBInstanceId": instanceId, 240 "BackupId": backupId, 241 } 242 _, err := region.rdsRequest("DeleteBackup", params) 243 return err 244 } 245 246 type SDBInstanceBackupJob struct { 247 BackupProgressStatus string 248 Process string 249 JobMode string 250 TaskAction string 251 BackupStatus string 252 BackupJobId string 253 } 254 255 type SDBInstanceBackupJobs struct { 256 BackupJob []SDBInstanceBackupJob 257 } 258 259 func (region *SRegion) GetDBInstanceBackupJobs(instanceId, jobId string) (*SDBInstanceBackupJobs, error) { 260 params := map[string]string{ 261 "DBInstanceId": instanceId, 262 "ClientToken": utils.GenRequestId(20), 263 "BackupMode": "Manual", 264 } 265 if len(jobId) > 0 { 266 params["BackupJobId"] = jobId 267 } 268 body, err := region.rdsRequest("DescribeBackupTasks", params) 269 if err != nil { 270 return nil, errors.Wrap(err, "DescribeBackupTasks") 271 } 272 273 jobs := SDBInstanceBackupJobs{} 274 275 err = body.Unmarshal(&jobs, "Items") 276 if err != nil { 277 return nil, errors.Wrapf(err, "body.Unmarshal(%s)", body) 278 } 279 280 return &jobs, nil 281 } 282 283 func (region *SRegion) waitBackupCreateComplete(instanceId, jobId string) error { 284 for i := 0; i < 20*40; i++ { 285 jobs, err := region.GetDBInstanceBackupJobs(instanceId, jobId) 286 if err != nil { 287 return errors.Wrapf(err, "region.GetDBInstanceBackupJobs(%s, %s)", instanceId, jobId) 288 } 289 if len(jobs.BackupJob) == 0 { 290 return nil 291 } 292 for _, job := range jobs.BackupJob { 293 log.Infof("instance %s backup job %s status: %s(%s)", instanceId, jobId, job.BackupStatus, job.Process) 294 if job.BackupStatus == "Finished" && job.BackupJobId == jobId { 295 return nil 296 } 297 if job.BackupStatus == "Failed" && job.BackupJobId == jobId { 298 return fmt.Errorf("instance %s backup job %s failed", instanceId, jobId) 299 } 300 } 301 time.Sleep(time.Second * 3) 302 } 303 return fmt.Errorf("timeout for waiting create job complete") 304 }