mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-07-01 02:24:47 +08:00
feat: rds recovery new instance from backup supported
This commit is contained in:
@@ -142,6 +142,9 @@ type DBInstanceCreateInput struct {
|
||||
// required: true
|
||||
DiskSizeGB int `json:"disk_size_gb"`
|
||||
|
||||
// 指定连接端口
|
||||
Port int `json:"port"`
|
||||
|
||||
// rds初始化密码
|
||||
// 阿里云不需要此参数
|
||||
// 华为云会默认创建一个用户,若不传此参数, 则为随机密码
|
||||
@@ -163,6 +166,9 @@ type DBInstanceCreateInput struct {
|
||||
|
||||
// swagger:ignore
|
||||
Provider string
|
||||
|
||||
// 从备份中创建新实例
|
||||
DBInstancebackupId string `json:"dbinstancebackup_id"`
|
||||
}
|
||||
|
||||
type SDBInstanceChangeConfigInput struct {
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
@@ -821,3 +822,15 @@ func NewIPv4AddrValidator(key string) *ValidatorIPv4Addr {
|
||||
v.SetParent(v)
|
||||
return v
|
||||
}
|
||||
|
||||
var ValidateModel = func(userCred mcclient.TokenCredential, manager db.IStandaloneModelManager, id *string) (db.IModel, error) {
|
||||
model, err := manager.FetchByIdOrName(userCred, *id)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(manager.Keyword(), *id)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
*id = model.GetId()
|
||||
return model, nil
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -55,6 +63,9 @@ type SManagedDBInstanceCreateConfig struct {
|
||||
ProjectId string
|
||||
|
||||
BillingCycle *billing.SBillingCycle
|
||||
|
||||
// 仅从备份恢复到新实例用到
|
||||
RdsId string
|
||||
}
|
||||
|
||||
type SManagedDBInstanceChangeConfig struct {
|
||||
|
||||
@@ -816,6 +816,9 @@ type ICloudDBInstanceBackup interface {
|
||||
GetBackupSizeMb() int
|
||||
GetDBNames() string
|
||||
GetBackupMode() string
|
||||
GetBackupMethod() TBackupMethod
|
||||
|
||||
CreateICloudDBInstance(opts *SManagedDBInstanceCreateConfig) (ICloudDBInstance, error)
|
||||
|
||||
Delete() error
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -369,6 +368,46 @@ func (backup *SDBInstanceBackup) GetIRegion() (cloudprovider.ICloudRegion, error
|
||||
}
|
||||
|
||||
func (backup *SDBInstanceBackup) GetIDBInstanceBackup() (cloudprovider.ICloudDBInstanceBackup, error) {
|
||||
if len(backup.ExternalId) == 0 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty external id")
|
||||
}
|
||||
if len(backup.DBInstanceId) > 0 {
|
||||
rds, err := backup.GetDBInstance()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetDBInstance")
|
||||
}
|
||||
iRds, err := rds.GetIDBInstance()
|
||||
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")
|
||||
}
|
||||
for i := range backups {
|
||||
if backups[i].GetGlobalId() == backup.ExternalId {
|
||||
return backups[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "search backup %s", backup.ExternalId)
|
||||
}
|
||||
|
||||
iRegion, err := backup.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "backup.GetIRegion")
|
||||
@@ -439,6 +478,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 {
|
||||
//有可能云上删除了实例,未删除备份
|
||||
@@ -497,6 +537,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 {
|
||||
@@ -591,3 +632,67 @@ 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 {
|
||||
network, _ := rds.GetDBNetwork()
|
||||
if network != nil {
|
||||
output.NetworkId = network.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
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -135,6 +136,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 {
|
||||
@@ -274,8 +278,18 @@ func (man *SDBInstanceManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field
|
||||
}
|
||||
|
||||
func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DBInstanceCreateInput) (*jsonutils.JSONDict, error) {
|
||||
if len(input.DBInstancebackupId) > 0 {
|
||||
_backup, err := validators.ValidateModel(userCred, DBInstanceBackupManager, &input.DBInstancebackupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
backup := _backup.(*SDBInstanceBackup)
|
||||
err = backup.fillRdsConfig(&input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
data := input.JSON(input)
|
||||
networkV := validators.NewModelIdOrNameValidator("network", "network", ownerId)
|
||||
addressV := validators.NewIPv4AddrValidator("address")
|
||||
secgroupV := validators.NewModelIdOrNameValidator("secgroup", "secgroup", ownerId)
|
||||
masterV := validators.NewModelIdOrNameValidator("master_instance", "dbinstance", ownerId)
|
||||
@@ -283,7 +297,6 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred
|
||||
zone2V := validators.NewModelIdOrNameValidator("zone2", "zone", ownerId)
|
||||
zone3V := validators.NewModelIdOrNameValidator("zone3", "zone", ownerId)
|
||||
keyV := map[string]validators.IValidator{
|
||||
"network": networkV,
|
||||
"address": addressV.Optional(true),
|
||||
"master": masterV.ModelIdKey("master_instance_id").Optional(true),
|
||||
"secgroup": secgroupV.Optional(true),
|
||||
@@ -318,10 +331,36 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred
|
||||
}
|
||||
}
|
||||
|
||||
network := networkV.Model.(*SNetwork)
|
||||
input.NetworkExternalId = network.ExternalId
|
||||
var vpc *SVpc
|
||||
var network *SNetwork
|
||||
if len(input.NetworkId) > 0 {
|
||||
_network, err := validators.ValidateModel(userCred, NetworkManager, &input.NetworkId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
network = _network.(*SNetwork)
|
||||
input.NetworkExternalId = network.ExternalId
|
||||
if len(input.Address) > 0 {
|
||||
ip := net.ParseIP(input.Address).To4()
|
||||
if ip == nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid address: %s", input.Address)
|
||||
}
|
||||
addr, _ := netutils.NewIPV4Addr(input.Address)
|
||||
if !network.IsAddressInRange(addr) {
|
||||
return nil, 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 nil, err
|
||||
}
|
||||
vpc = _vpc.(*SVpc)
|
||||
} else {
|
||||
return nil, httperrors.NewMissingParameterError("vpc_id")
|
||||
}
|
||||
|
||||
vpc := network.GetVpc()
|
||||
input.VpcId = vpc.Id
|
||||
input.ManagerId = vpc.ManagerId
|
||||
cloudprovider := vpc.GetCloudprovider()
|
||||
|
||||
@@ -154,6 +154,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -285,6 +285,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")
|
||||
}
|
||||
|
||||
@@ -1738,6 +1738,73 @@ 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())
|
||||
|
||||
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) error {
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
@@ -2347,14 +2414,9 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceBackup(ct
|
||||
return nil, errors.Wrapf(err, "iRegion.GetIDBInstanceBackupById(%s)", backupId)
|
||||
}
|
||||
|
||||
_, 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, "")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
66
pkg/mcclient/options/dbinstances.go
Normal file
66
pkg/mcclient/options/dbinstances.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
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:"-"`
|
||||
DBInstancebackupId string `help:"create dbinstance from backup" json:"dbinstancebackup_id"`
|
||||
}
|
||||
|
||||
func (opts *DBInstanceCreateOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
params, err := StructToParams(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Tagparams := jsonutils.NewDict()
|
||||
for _, tag := range opts.Tags {
|
||||
info := strings.Split(tag, "=")
|
||||
if len(info) == 2 {
|
||||
if len(info[0]) == 0 {
|
||||
return nil, fmt.Errorf("invalidate tag info %s", tag)
|
||||
}
|
||||
Tagparams.Add(jsonutils.NewString(info[1]), info[0])
|
||||
} else if len(info) == 1 {
|
||||
Tagparams.Add(jsonutils.NewString(info[0]), info[0])
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalidate tag info %s", tag)
|
||||
}
|
||||
}
|
||||
params.Add(Tagparams, "__meta__")
|
||||
return params, nil
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@ package multicloud
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SDBInstanceBackupBase struct {
|
||||
@@ -35,3 +38,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
|
||||
|
||||
Reference in New Issue
Block a user