Merge pull request #8876 from ioito/feat/qx-rds-create-by-backup

feat: rds recovery new instance from backup supported
This commit is contained in:
Zexi Li
2020-11-19 20:52:52 +08:00
committed by GitHub
15 changed files with 343 additions and 69 deletions
+6
View File
@@ -135,6 +135,9 @@ type DBInstanceCreateInput struct {
// required: true
DiskSizeGB int `json:"disk_size_gb"`
// 指定连接端口
Port int `json:"port"`
// rds初始化密码
// 阿里云不需要此参数
// 华为云会默认创建一个用户,若不传此参数, 则为随机密码
@@ -154,6 +157,9 @@ type DBInstanceCreateInput struct {
// rds实例内存大小
// 若指定实例套餐,此参数将根据套餐设置
VmemSizeMb int `json:"vmem_size_mb"`
// 从备份中创建新实例
DBInstancebackupId string `json:"dbinstancebackup_id"`
}
type SDBInstanceChangeConfigInput struct {
+11
View File
@@ -16,6 +16,14 @@ package cloudprovider
import "yunion.io/x/onecloud/pkg/util/billing"
type TBackupMethod string
const (
BackupMethodLogical = TBackupMethod("Logical")
BackupMethodPhysical = TBackupMethod("Physical")
BackupMethodUnknown = TBackupMethod("")
)
type SDBInstanceNetwork struct {
IP string
NetworkId string
@@ -61,6 +69,9 @@ type SManagedDBInstanceCreateConfig struct {
BillingCycle *billing.SBillingCycle
Tags map[string]string
// 仅从备份恢复到新实例用到
RdsId string
}
type SManagedDBInstanceChangeConfig struct {
+3
View File
@@ -848,6 +848,9 @@ type ICloudDBInstanceBackup interface {
GetBackupSizeMb() int
GetDBNames() string
GetBackupMode() string
GetBackupMethod() TBackupMethod
CreateICloudDBInstance(opts *SManagedDBInstanceCreateConfig) (ICloudDBInstance, error)
Delete() error
}
+24
View File
@@ -866,6 +866,10 @@ func syncDBInstanceResource(ctx context.Context, userCred mcclient.TokenCredenti
if err != nil {
log.Errorf("syncDBInstanceAccounts: %v", err)
}
err = syncDBInstanceBackups(ctx, userCred, syncResults, localInstance, remoteInstance)
if err != nil {
log.Errorf("syncDBInstanceBackups: %v", err)
}
}
func syncDBInstanceNetwork(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) error {
@@ -901,6 +905,26 @@ func syncDBInstanceSecgroups(ctx context.Context, userCred mcclient.TokenCredent
return nil
}
func syncDBInstanceBackups(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) error {
backups, err := remoteInstance.GetIDBInstanceBackups()
if err != nil {
return errors.Wrapf(err, "GetIDBInstanceBackups")
}
region := localInstance.GetRegion()
provider := localInstance.GetCloudprovider()
result := DBInstanceBackupManager.SyncDBInstanceBackups(ctx, userCred, provider, localInstance, region, backups)
syncResults.Add(DBInstanceBackupManager, result)
msg := result.Result()
log.Infof("SyncDBInstanceBackups for dbinstance %s result: %s", localInstance.Name, msg)
if result.IsError() {
return result.AllError()
}
return nil
}
func syncDBInstanceParameters(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) error {
parameters, err := remoteInstance.GetIDBInstanceParameters()
if err != nil {
+88 -4
View File
@@ -85,9 +85,8 @@ type SDBInstanceBackup struct {
// example: 32
BackupSizeMb int `nullable:"false" list:"user" json:"backup_size_mb"`
// RDS实例Id
// example: 239b9663-6d06-4ef4-8cfc-320a7fb6660d
// DBInstanceId string `width:"36" charset:"ascii" name:"dbinstance_id" nullable:"false" list:"user" create:"required" index:"true"`
// 备份方式 Logical|Physical
BackupMethod string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"optional" json:"backup_method"`
}
func (manager *SDBInstanceBackupManager) GetContextManagers() [][]db.IModelManager {
@@ -381,6 +380,22 @@ func (backup *SDBInstanceBackup) GetIDBInstanceBackup() (cloudprovider.ICloudDBI
if err != nil {
return nil, errors.Wrapf(err, "GetIDBInstance")
}
err = cloudprovider.Wait(time.Second*3, time.Second*15, func() (bool, error) {
backups, err := iRds.GetIDBInstanceBackups()
if err != nil {
return false, errors.Wrapf(err, "GetIDBInstanceBackups")
}
for i := range backups {
if backups[i].GetGlobalId() == backup.ExternalId {
return true, nil
}
}
log.Warningf("failed to found backup %s", backup.ExternalId)
return false, nil
})
if err != nil {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "timeout for search backup %s", backup.ExternalId)
}
backups, err := iRds.GetIDBInstanceBackups()
if err != nil {
return nil, errors.Wrapf(err, "GetIDBInstanceBackups")
@@ -390,7 +405,7 @@ func (backup *SDBInstanceBackup) GetIDBInstanceBackup() (cloudprovider.ICloudDBI
return backups[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "externalId: %s", backup.ExternalId)
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "search backup %s", backup.ExternalId)
}
iRegion, err := backup.GetIRegion()
@@ -464,6 +479,7 @@ func (self *SDBInstanceBackup) SyncWithCloudDBInstanceBackup(
self.Engine = extBackup.GetEngine()
self.EngineVersion = extBackup.GetEngineVersion()
self.DBNames = extBackup.GetDBNames()
self.BackupMethod = string(extBackup.GetBackupMethod())
if dbinstanceId := extBackup.GetDBInstanceId(); len(dbinstanceId) > 0 {
//有可能云上删除了实例,未删除备份
@@ -522,6 +538,7 @@ func (manager *SDBInstanceBackupManager) newFromCloudDBInstanceBackup(
backup.BackupSizeMb = extBackup.GetBackupSizeMb()
backup.DBNames = extBackup.GetDBNames()
backup.BackupMode = extBackup.GetBackupMode()
backup.BackupMethod = string(extBackup.GetBackupMethod())
backup.ExternalId = extBackup.GetGlobalId()
if dbinstanceId := extBackup.GetDBInstanceId(); len(dbinstanceId) > 0 {
@@ -616,3 +633,70 @@ func (manager *SDBInstanceBackupManager) ListItemExportKeys(ctx context.Context,
func (self *SDBInstanceBackup) GetChangeOwnerCandidateDomainIds() []string {
return self.SManagedResourceBase.GetChangeOwnerCandidateDomainIds()
}
func (self *SDBInstanceBackup) fillRdsConfig(output *api.DBInstanceCreateInput) error {
if self.Status != api.DBINSTANCE_BACKUP_READY {
return fmt.Errorf("backup %s status is %s require %s", self.Name, self.Status, api.DBINSTANCE_BACKUP_READY)
}
if len(self.DBInstanceId) == 0 {
if len(self.Engine) == 0 {
return fmt.Errorf("backup engine %s is unknown", self.Name)
}
output.Engine = self.Engine
if len(self.EngineVersion) == 0 {
return fmt.Errorf("backup engine version %s is unknown", self.Name)
}
output.EngineVersion = self.EngineVersion
return nil
}
rds, err := self.GetDBInstance()
if err != nil {
return errors.Wrapf(err, "backup.GetDBInstance")
}
if len(output.NetworkId) == 0 {
networks, err := rds.GetDBNetworks()
if err != nil {
return errors.Wrapf(err, "GetDBNetworks")
}
if len(networks) > 0 {
output.NetworkId = networks[0].NetworkId
}
}
if output.VcpuCount == 0 {
output.VcpuCount = rds.VcpuCount
}
if output.VmemSizeMb == 0 {
output.VmemSizeMb = rds.VmemSizeMb
}
if output.DiskSizeGB == 0 {
output.DiskSizeGB = rds.DiskSizeGB
}
if output.Port == 0 {
output.Port = rds.Port
}
if len(output.Category) == 0 {
output.Category = rds.Category
}
if len(output.StorageType) == 0 {
output.StorageType = rds.StorageType
}
output.Engine = rds.Engine
output.EngineVersion = rds.EngineVersion
if len(output.InstanceType) == 0 {
output.InstanceType = rds.InstanceType
}
if len(output.VpcId) == 0 {
output.VpcId = rds.VpcId
}
if len(output.Zone1) == 0 {
output.Zone1 = rds.Zone1
}
if len(output.Zone2) == 0 {
output.Zone2 = rds.Zone2
}
if len(output.Zone3) == 0 {
output.Zone3 = rds.Zone3
}
return nil
}
+39 -18
View File
@@ -132,6 +132,9 @@ type SDBInstance struct {
Zone2 string `width:"36" charset:"ascii" nullable:"false" create:"optional" list:"user"`
// 可用区3
Zone3 string `width:"36" charset:"ascii" nullable:"false" create:"optional" list:"user"`
// 从备份创建新实例
DBInstancebackupId string `width:"36" name:"dbinstancebackup_id" charset:"ascii" nullable:"false" create:"optional"`
}
func (manager *SDBInstanceManager) GetContextManagers() [][]db.IModelManager {
@@ -284,6 +287,17 @@ func (manager *SDBInstanceManager) BatchCreateValidateCreateData(ctx context.Con
}
func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DBInstanceCreateInput) (api.DBInstanceCreateInput, error) {
if len(input.DBInstancebackupId) > 0 {
_backup, err := validators.ValidateModel(userCred, DBInstanceBackupManager, &input.DBInstancebackupId)
if err != nil {
return input, err
}
backup := _backup.(*SDBInstanceBackup)
err = backup.fillRdsConfig(&input)
if err != nil {
return input, err
}
}
for _, v := range map[string]*string{"zone1": &input.Zone1, "zone2": &input.Zone2, "zone3": &input.Zone3} {
if len(*v) > 0 {
_, err := validators.ValidateModel(userCred, ZoneManager, v)
@@ -298,28 +312,35 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred
return input, httperrors.NewWeakPasswordError()
}
}
if len(input.NetworkId) == 0 {
return input, httperrors.NewMissingParameterError("network_id")
}
_network, err := validators.ValidateModel(userCred, NetworkManager, &input.NetworkId)
if err != nil {
return input, err
}
network := _network.(*SNetwork)
if len(input.Address) > 0 {
ip := net.ParseIP(input.Address).To4()
if ip == nil {
return input, httperrors.NewInputParameterError("invalid address: %s", input.Address)
var vpc *SVpc
var network *SNetwork
if len(input.NetworkId) > 0 {
_network, err := validators.ValidateModel(userCred, NetworkManager, &input.NetworkId)
if err != nil {
return input, err
}
addr, _ := netutils.NewIPV4Addr(input.Address)
if !network.IsAddressInRange(addr) {
return input, httperrors.NewInputParameterError("Ip %s not in network %s(%s) range", input.Address, network.Name, network.Id)
network = _network.(*SNetwork)
if len(input.Address) > 0 {
ip := net.ParseIP(input.Address).To4()
if ip == nil {
return input, httperrors.NewInputParameterError("invalid address: %s", input.Address)
}
addr, _ := netutils.NewIPV4Addr(input.Address)
if !network.IsAddressInRange(addr) {
return input, httperrors.NewInputParameterError("Ip %s not in network %s(%s) range", input.Address, network.Name, network.Id)
}
}
vpc = network.GetVpc()
} else if len(input.VpcId) > 0 {
_vpc, err := validators.ValidateModel(userCred, VpcManager, &input.VpcId)
if err != nil {
return input, err
}
vpc = _vpc.(*SVpc)
} else {
return input, httperrors.NewMissingParameterError("vpc_id")
}
vpc := network.GetVpc()
input.VpcId = vpc.Id
input.ManagerId = vpc.ManagerId
cloudprovider := vpc.GetCloudprovider()
+1
View File
@@ -161,6 +161,7 @@ type IDBInstanceDriver interface {
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
+18 -17
View File
@@ -1000,25 +1000,26 @@ func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Contex
return input, httperrors.NewInputParameterError("slave dbinstance not support prepaid billing type")
}
wire := network.GetWire()
if wire == nil {
return input, httperrors.NewGeneralError(fmt.Errorf("failed to found wire for network %s(%s)", network.Name, network.Id))
}
zone := wire.GetZone()
if zone == nil {
return input, httperrors.NewGeneralError(fmt.Errorf("failed to found zone for wire %s(%s)", wire.Name, wire.Id))
}
match := false
for _, sku := range skus {
if utils.IsInStringArray(zone.Id, []string{sku.Zone1, sku.Zone2, sku.Zone3}) {
match = true
break
if network != nil {
wire := network.GetWire()
if wire == nil {
return input, httperrors.NewGeneralError(fmt.Errorf("failed to found wire for network %s(%s)", network.Name, network.Id))
}
zone := wire.GetZone()
if zone == nil {
return input, httperrors.NewGeneralError(fmt.Errorf("failed to found zone for wire %s(%s)", wire.Name, wire.Id))
}
}
if !match {
return input, httperrors.NewInputParameterError("failed to match any skus in the network %s(%s) zone %s(%s)", network.Name, network.Id, zone.Name, zone.Id)
match := false
for _, sku := range skus {
if utils.IsInStringArray(zone.Id, []string{sku.Zone1, sku.Zone2, sku.Zone3}) {
match = true
break
}
}
if !match {
return input, httperrors.NewInputParameterError("failed to match any skus in the network %s(%s) zone %s(%s)", network.Name, network.Id, zone.Name, zone.Id)
}
}
var master *models.SDBInstance
+4
View File
@@ -295,6 +295,10 @@ func (self *SBaseRegionDriver) RequestCreateDBInstance(ctx context.Context, user
return fmt.Errorf("Not Implement RequestCreateDBInstance")
}
func (self *SBaseRegionDriver) RequestCreateDBInstanceFromBackup(ctx context.Context, userCred mcclient.TokenCredential, dbinstance *models.SDBInstance, task taskman.ITask) error {
return fmt.Errorf("Not Implement RequestCreateDBInstanceFromBackup")
}
func (self *SBaseRegionDriver) RequestCreateDBInstanceBackup(ctx context.Context, userCred mcclient.TokenCredential, dbinstance *models.SDBInstance, backup *models.SDBInstanceBackup, task taskman.ITask) error {
return fmt.Errorf("Not Implement RequestCreateDBInstanceBackup")
}
+81 -7
View File
@@ -1801,6 +1801,85 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstance(ctx cont
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceFromBackup(ctx context.Context, userCred mcclient.TokenCredential, rds *models.SDBInstance, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
_backup, err := models.DBInstanceBackupManager.FetchById(rds.DBInstancebackupId)
if err != nil {
return nil, errors.Wrapf(err, "DBInstanceBackupManager.FetchById(%s)", rds.DBInstancebackupId)
}
backup := _backup.(*models.SDBInstanceBackup)
iBackup, err := backup.GetIDBInstanceBackup()
if err != nil {
return nil, errors.Wrapf(err, "backup.GetIDBInstanceBackup")
}
vpc, err := rds.GetVpc()
if err != nil {
return nil, errors.Wrap(err, "rds.GetVpc()")
}
desc := cloudprovider.SManagedDBInstanceCreateConfig{
Name: rds.Name,
Description: rds.Description,
StorageType: rds.StorageType,
DiskSizeGB: rds.DiskSizeGB,
VcpuCount: rds.VcpuCount,
VmemSizeMb: rds.VmemSizeMb,
VpcId: vpc.ExternalId,
Engine: rds.Engine,
EngineVersion: rds.EngineVersion,
Category: rds.Category,
Port: rds.Port,
}
if len(backup.DBInstanceId) > 0 {
parentRds, err := backup.GetDBInstance()
if err != nil {
return nil, errors.Wrapf(err, "backup.GetDBInstance")
}
desc.RdsId = parentRds.ExternalId
}
log.Debugf("create from backup params: %s", jsonutils.Marshal(desc).String())
networks, err := rds.GetDBNetworks()
if err != nil {
return nil, errors.Wrapf(err, "dbinstance.GetDBNetworks")
}
if len(networks) > 0 {
net, err := networks[0].GetNetwork()
if err != nil {
return nil, errors.Wrapf(err, "GetNetwork")
}
desc.NetworkId, desc.Address = net.ExternalId, networks[0].IpAddr
}
if rds.BillingType == billing_api.BILLING_TYPE_PREPAID {
bc, err := billing.ParseBillingCycle(rds.BillingCycle)
if err != nil {
log.Errorf("failed to parse billing cycle %s: %v", rds.BillingCycle, err)
} else if bc.IsValid() {
desc.BillingCycle = &bc
desc.BillingCycle.AutoRenew = rds.AutoRenew
}
}
iRds, err := iBackup.CreateICloudDBInstance(&desc)
if err != nil {
return nil, errors.Wrapf(err, "iBackup.CreateICloudDBInstance")
}
err = db.SetExternalId(rds, userCred, iRds.GetGlobalId())
if err != nil {
return nil, errors.Wrapf(err, "db.SetExternalId")
}
err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*5, time.Hour*1)
if err != nil {
return nil, errors.Wrapf(err, "cloudprovider.WaitStatus runing")
}
return nil, nil
})
return nil
}
func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error {
task.ScheduleRun(nil)
return nil
@@ -2433,14 +2512,9 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceBackup(ct
return nil, errors.Wrapf(err, "backup.GetIDBInstanceBackup")
}
_, err = db.Update(backup, func() error {
backup.StartTime = iBackup.GetStartTime()
backup.EndTime = iBackup.GetEndTime()
backup.BackupSizeMb = iBackup.GetBackupSizeMb()
return nil
})
err = backup.SyncWithCloudDBInstanceBackup(ctx, userCred, iBackup, instance.GetCloudprovider())
if err != nil {
return nil, errors.Wrap(err, "db.Update")
log.Warningf("sync backup info error: %v", err)
}
instance.SetStatus(userCred, api.DBINSTANCE_RUNNING, "")
+9 -4
View File
@@ -48,12 +48,17 @@ func (self *DBInstanceCreateTask) OnInit(ctx context.Context, obj db.IStandalone
self.CreateDBInstance(ctx, dbinstance)
}
func (self *DBInstanceCreateTask) CreateDBInstance(ctx context.Context, dbinstance *models.SDBInstance) {
region := dbinstance.GetRegion()
func (self *DBInstanceCreateTask) CreateDBInstance(ctx context.Context, rds *models.SDBInstance) {
region := rds.GetRegion()
self.SetStage("OnCreateDBInstanceComplete", nil)
err := region.GetDriver().RequestCreateDBInstance(ctx, self.UserCred, dbinstance, self)
var err error
if len(rds.DBInstancebackupId) > 0 {
err = region.GetDriver().RequestCreateDBInstanceFromBackup(ctx, self.UserCred, rds, self)
} else {
err = region.GetDriver().RequestCreateDBInstance(ctx, self.UserCred, rds, self)
}
if err != nil {
self.taskFailed(ctx, dbinstance, err)
self.taskFailed(ctx, rds, err)
return
}
}
+18 -17
View File
@@ -22,23 +22,24 @@ import (
)
type DBInstanceCreateOptions struct {
NAME string `help:"DBInstance Name"`
InstanceType string `help:"InstanceType for DBInstance"`
VcpuCount int `help:"Core of cpu for DBInstance"`
VmemSizeMb int `help:"Memory size of DBInstance"`
Port int `help:"Port of DBInstance"`
Category string `help:"Category of DBInstance"`
Network string `help:"Network of DBInstance"`
Address string `help:"Address of DBInstance"`
Engine string `help:"Engine of DBInstance"`
EngineVersion string `help:"EngineVersion of DBInstance Engine"`
StorageType string `help:"StorageTyep of DBInstance"`
Secgroup string `help:"Secgroup name or Id for DBInstance"`
Zone string `help:"ZoneId or name for DBInstance"`
DiskSizeGB int `help:"Storage size for DBInstance"`
Duration string `help:"Duration for DBInstance"`
AllowDelete *bool `help:"not lock dbinstance" `
Tags []string `help:"Tags info,prefix with 'user:', eg: user:project=default" json:"-"`
NAME string `help:"DBInstance Name"`
InstanceType string `help:"InstanceType for DBInstance"`
VcpuCount int `help:"Core of cpu for DBInstance"`
VmemSizeMb int `help:"Memory size of DBInstance"`
Port int `help:"Port of DBInstance"`
Category string `help:"Category of DBInstance"`
Network string `help:"Network of DBInstance"`
Address string `help:"Address of DBInstance"`
Engine string `help:"Engine of DBInstance"`
EngineVersion string `help:"EngineVersion of DBInstance Engine"`
StorageType string `help:"StorageTyep of DBInstance"`
Secgroup string `help:"Secgroup name or Id for DBInstance"`
Zone string `help:"ZoneId or name for DBInstance"`
DiskSizeGB int `help:"Storage size for DBInstance"`
Duration string `help:"Duration for DBInstance"`
AllowDelete *bool `help:"not lock dbinstance" `
Tags []string `help:"Tags info,prefix with 'user:', eg: user:project=default" json:"-"`
DBInstancebackupId string `help:"create dbinstance from backup" json:"dbinstancebackup_id"`
}
func (opts *DBInstanceCreateOptions) Params() (*jsonutils.JSONDict, error) {
+31 -2
View File
@@ -19,8 +19,7 @@ import (
"strings"
"time"
"github.com/coredns/coredns/plugin/pkg/log"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
@@ -325,3 +324,33 @@ func (region *SRegion) waitBackupCreateComplete(instanceId, jobId string) (strin
}
return "", fmt.Errorf("failed to found backup job %s backupid", jobId)
}
func (self *SDBInstanceBackup) GetBackupMethod() cloudprovider.TBackupMethod {
return cloudprovider.TBackupMethod(self.BackupMethod)
}
func (self *SDBInstanceBackup) CreateICloudDBInstance(opts *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) {
rdsId, err := self.region.CreateDBInstanceByBackup(self.BackupId, opts)
if err != nil {
return nil, errors.Wrapf(err, "CreateDBInstanceByBackup")
}
return self.region.GetDBInstanceDetail(rdsId)
}
func (self *SRegion) CreateDBInstanceByBackup(backupId string, opts *cloudprovider.SManagedDBInstanceCreateConfig) (string, error) {
params := map[string]string{
"DBInstanceId": opts.RdsId,
"DBInstanceStorageType": opts.StorageType,
"PayType": "Postpaid",
"BackupId": backupId,
}
resp, err := self.rdsRequest("CloneDBInstance", params)
if err != nil {
return "", errors.Wrapf(err, "rdsRequest")
}
rdsId, err := resp.GetString("DBInstanceId")
if err != nil {
return "", fmt.Errorf("missing DBInstanceId after CloneDBInstance")
}
return rdsId, nil
}
+8
View File
@@ -36,3 +36,11 @@ func (backup *SDBInstanceBackupBase) Delete() error {
func (backup *SDBInstanceBackupBase) GetProjectId() string {
return ""
}
func (backup *SDBInstanceBackupBase) CreateICloudDBInstance(opts *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) {
return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateICloudDBInstance")
}
func (backup *SDBInstanceBackupBase) GetBackupMethod() cloudprovider.TBackupMethod {
return cloudprovider.BackupMethodUnknown
}
@@ -23,6 +23,7 @@ import (
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/multicloud"
)
type OperationError struct {
@@ -32,6 +33,7 @@ type OperationError struct {
}
type SDBInstanceBackup struct {
multicloud.SDBInstanceBackupBase
rds *SDBInstance
Kind string