mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
feature: add qcloud rds support
This commit is contained in:
@@ -15,44 +15,13 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type DBInstanceSkuListOption struct {
|
||||
options.BaseListOptions
|
||||
Engine string
|
||||
EngineVersion string
|
||||
Category string
|
||||
StorageType string
|
||||
Cloudregion string
|
||||
}
|
||||
R(&DBInstanceSkuListOption{}, "dbinstance-sku-list", "List dbinstance skus", func(s *mcclient.ClientSession, args *DBInstanceSkuListOption) error {
|
||||
params, err := options.ListStructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.DBInstanceSkus.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.DBInstanceSkus.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type DBInstanceSkuIdOption struct {
|
||||
ID string `help:"DBInstance Id or name"`
|
||||
}
|
||||
|
||||
R(&DBInstanceSkuIdOption{}, "dbinstance-sku-show", "Show dbinstance sku details", func(s *mcclient.ClientSession, args *DBInstanceSkuIdOption) error {
|
||||
result, err := modules.DBInstanceSkus.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
cmd := shell.NewResourceCmd(&modules.DBInstanceSkus).WithKeyword("dbinstance-sku")
|
||||
cmd.List(&options.DBInstanceSkuListOption{})
|
||||
cmd.Show(&options.DBInstanceSkuIdOption{})
|
||||
}
|
||||
|
||||
@@ -107,19 +107,10 @@ type DBInstanceCreateInput struct {
|
||||
//
|
||||
// | 平台 | 支持类型 | 说明 |
|
||||
// | ----- | ------ | --- |
|
||||
// | 华为云 |ha, single, replica| |
|
||||
// | 阿里云 |basic, high_availability, always_on, finance||
|
||||
// | Google |Zonal, Regional | |
|
||||
// 翻译:
|
||||
// basic: 基础版
|
||||
// high_availability: 高可用
|
||||
// always_on: 集群版
|
||||
// finance: 金融版, 三节点
|
||||
// ha: 高可用
|
||||
// single: 单机
|
||||
// replica: 只读
|
||||
// Zonal: 单区域
|
||||
// Regional: 区域级
|
||||
// | 华为云 |ha, single, replica| ha: 高可用, single: 单机, replica: 只读|
|
||||
// | 阿里云 |basic, high_availability, always_on, finance|basic: 基础版, high_availability: 高可用, always_on: 集群版, finance: 金融版, 三节点|
|
||||
// | Google |Zonal, Regional | Zonal: 单区域, Regional: 区域级|
|
||||
// | 腾讯云 |fe, ha, basic | ha: 高可用, basic: 基础版, fe: 金融版|
|
||||
// required: true
|
||||
Category string `json:"category"`
|
||||
|
||||
@@ -127,13 +118,12 @@ type DBInstanceCreateInput struct {
|
||||
//
|
||||
//
|
||||
//
|
||||
// | 平台 | 支持类型 |
|
||||
// | 华为云 |SSD, SAS, SATA|
|
||||
// | 阿里云 |local_ssd, cloud_essd, cloud_ssd|
|
||||
// | Google |PD_SSD, PD_HDD|
|
||||
// 翻译:
|
||||
// PD_SSD: SSD
|
||||
// PD_HDD: HDD
|
||||
// | 平台 | 支持类型 | 说明 |
|
||||
// | ----- | ------ | --- |
|
||||
// | 华为云 |SSD, SAS, SATA| |
|
||||
// | 阿里云 |local_ssd, cloud_essd, cloud_ssd| |
|
||||
// | Google |PD_SSD, PD_HDD| PD_SSD: SSD, PD_HDD: HDD|
|
||||
// | 腾讯云 |cloud_ssd, local_ssd| |
|
||||
// required: true
|
||||
StorageType string `json:"storage_type"`
|
||||
|
||||
@@ -146,6 +136,7 @@ type DBInstanceCreateInput struct {
|
||||
// 阿里云不需要此参数
|
||||
// 华为云会默认创建一个用户,若不传此参数, 则为随机密码
|
||||
// 谷歌云会默认创建一个用户,若不传此参数, 则为随机密码
|
||||
// 腾讯云会默认创建一个用户,若不传此参数, 则为随机密码
|
||||
Password string `json:"password"`
|
||||
|
||||
// 是否不设置初始密码
|
||||
|
||||
@@ -48,6 +48,7 @@ type DBInstanceAccountCreateInput struct {
|
||||
// | ---- |------- |
|
||||
// | Aliyun |MySQL, MariaBD, SQLServer |
|
||||
// | 华为云 |MySQL, MariaBD |
|
||||
// | 腾讯云 |MySQL |
|
||||
// required: true
|
||||
// 阿里云SQL Server 2017集群版不支持创建账号
|
||||
// 实例状态必须是运行中
|
||||
|
||||
@@ -16,6 +16,7 @@ package compute
|
||||
|
||||
const (
|
||||
//实例状态
|
||||
DBINSTANCE_INIT = "init" //初始化
|
||||
DBINSTANCE_DEPLOYING = "deploying" //部署中
|
||||
DBINSTANCE_RUNNING = "running" //运行中
|
||||
DBINSTANCE_REBOOTING = "rebooting" //重启中
|
||||
@@ -99,6 +100,11 @@ const (
|
||||
ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON = "always_on" //集群版
|
||||
ALIYUN_DBINSTANCE_CATEGORY_FINANCE = "finance" //金融版
|
||||
|
||||
//腾讯云实例类型
|
||||
QCLOUD_DBINSTANCE_CATEGORY_BASIC = "basic" //基础版
|
||||
QCLOUD_DBINSTANCE_CATEGORY_HA = "ha" //高可用
|
||||
QCLOUD_DBINSTANCE_CATEGORY_FINANCE = "fe" //金融版
|
||||
|
||||
//华为云实例类型
|
||||
HUAWEI_DBINSTANCE_CATEGORY_HA = "ha" //主备
|
||||
HUAWEI_DBINSTANCE_CATEGORY_SINGLE = "single" //单机
|
||||
@@ -118,6 +124,11 @@ const (
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_ULTRAHIGHPRO = "ULTRAHIGHPRO"
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_COMMON = "COMMON"
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_HIGH = "HIGH"
|
||||
|
||||
//腾讯云
|
||||
QCLOUD_DBINSTANCE_STORAGE_TYPE_LOCAL_SSD = "local_ssd" //本地盘SSD盘
|
||||
QCLOUD_DBINSTANCE_STORAGE_TYPE_CLOUD_SSD = "cloud_ssd" //SSD云盘
|
||||
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -128,4 +139,20 @@ var (
|
||||
ALIYUN_SQL_SERVER_DENY_KEYWORD []string = []string{
|
||||
"root", " admin", " eagleye", " master", " aurora", " sa", " sysadmin", " administrator", " mssqld", " public", " securityadmin", " serveradmin", " setupadmin", " processadmin", " diskadmin", " dbcreator", " bulkadmin", " tempdb", " msdb", " model", " distribution", " mssqlsystemresource", " guest", " add", " except", " percent", " all", " exec", " plan", " alter", " execute", " precision", " and", " exists", " primary", " any", " exit", " print", " as", " fetch", " proc", " asc", " file", " procedure", " authorization", " fillfactor", " public", " backup", " for", " raiserror", " begin", " foreign", " read", " between", " freetext", " readtext", " break", " freetexttable", " reconfigure", " browse", " from", " references", " bulk", " full", " replication", " by", " function", " restore", " cascade", " goto", " restrict", " case", " grant", " return", " check", " group", " revoke", " checkpoint", " having", " right", " close", " holdlock", " rollback", " clustered", " identity", " rowcount", " coalesce", " identity_insert", " rowguidcol", " collate", " identitycol", " rule", " column", " if", " save", " commit", " in", " schema", " compute", " index", " select", " constraint", " inner", " session_user", " contains", " insert", " set", " containstable", " intersect", " setuser", " continue", " into", " shutdown", " convert", " is", " some", " create", " join", " statistics", " cross", " key", " system_user", " current", " kill", " table", " current_date", " left", " textsize", " current_time", " like", " then", " current_timestamp", " lineno", " to", " current_user", " load", " top", " cursor", " national", " tran", " database", " nocheck", " transaction", " dbcc", " nonclustered", " trigger", " deallocate", " not", " truncate", " declare", " null", " tsequal", " default", " nullif", " union", " delete", " of", " unique", " deny", " off", " update", " desc", " offsets", " updatetext", " disk", " on", " use", " distinct", " open", " user", " distributed", " opendatasource", " values", " double", " openquery", " varying", " drop", " openrowset", " view", " dummy", " openxml", " waitfor", " dump", " option", " when", " else", " or", " where", " end", " order", " while", " errlvl", " outer", " with", " escape", " over", " writetext", " galaxy",
|
||||
}
|
||||
|
||||
RW_PRIVILEGE_SET = []string{
|
||||
"SELECT", "INSERT", "UPDATE", "DELETE", "CREATE",
|
||||
"DROP", "REFERENCES", "INDEX", "ALTER", "CREATE TEMPORARY TABLES",
|
||||
"LOCK TABLES", "EXECUTE", "CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE",
|
||||
"ALTER ROUTINE", "EVENT", "TRIGGER", "PROCESS", "REPLICATION SLAVE",
|
||||
"REPLICATION CLIENT",
|
||||
}
|
||||
R_PRIVILEGE_SET = []string{"SELECT", "LOCK TABLES", "SHOW VIEW", "PROCESS", "REPLICATION SLAVE", "REPLICATION CLIENT"}
|
||||
QCLOUD_RW_PRIVILEGE_SET = []string{
|
||||
"SELECT", "INSERT", "UPDATE", "DELETE", "CREATE",
|
||||
"DROP", "REFERENCES", "INDEX", "ALTER", "CREATE TEMPORARY TABLES",
|
||||
"LOCK TABLES", "EXECUTE", "CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE",
|
||||
"ALTER ROUTINE", "EVENT", "TRIGGER",
|
||||
}
|
||||
QCLOUD_R_PRIVILEGE_SET = []string{"SELECT", "LOCK TABLES", "SHOW VIEW"}
|
||||
)
|
||||
|
||||
@@ -44,6 +44,7 @@ type DBInstanceDatabaseCreateInput struct {
|
||||
// | ---- |------- |
|
||||
// | Aliyun |MySQL, MariaBD, SQLServer |
|
||||
// | 华为云 |MySQL, MariaBD |
|
||||
// | 腾讯云 | |
|
||||
// required: true
|
||||
// 阿里云SQL Server 2017集群版不支持创建数据库
|
||||
// 阿里云只读实例不支持创建数据库
|
||||
|
||||
@@ -16,4 +16,5 @@ package compute
|
||||
|
||||
const (
|
||||
DBINSTANCE_SKU_AVAILABLE = "available"
|
||||
DBINSTANCE_SKU_SOLDOUT = "soldout"
|
||||
)
|
||||
|
||||
@@ -26,19 +26,24 @@ type SExtraIp struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
type SZoneInfo struct {
|
||||
Zone1 string
|
||||
Zone2 string
|
||||
Zone3 string
|
||||
ZoneId string
|
||||
}
|
||||
|
||||
type SInstanceType struct {
|
||||
InstanceType string
|
||||
ZoneIds []string
|
||||
SZoneInfo
|
||||
}
|
||||
|
||||
type SManagedDBInstanceCreateConfig struct {
|
||||
Name string
|
||||
Description string
|
||||
StorageType string
|
||||
DiskSizeGB int
|
||||
SInstanceType
|
||||
Name string
|
||||
Description string
|
||||
StorageType string
|
||||
DiskSizeGB int
|
||||
InstanceType string
|
||||
InstanceTypes []SInstanceType
|
||||
VcpuCount int
|
||||
VmemSizeMb int
|
||||
VpcId string
|
||||
@@ -61,6 +66,8 @@ type SManagedDBInstanceChangeConfig struct {
|
||||
DiskSizeGB int
|
||||
StorageType string
|
||||
InstanceType string
|
||||
VcpuCount int
|
||||
VmemSizeMb int
|
||||
}
|
||||
|
||||
type SDBInstanceDatabaseCreateConfig struct {
|
||||
@@ -77,6 +84,7 @@ type SDBInstancePrivilege struct {
|
||||
|
||||
type SDBInstanceAccountCreateConfig struct {
|
||||
Name string
|
||||
Host string
|
||||
Description string
|
||||
Password string
|
||||
}
|
||||
|
||||
@@ -833,7 +833,9 @@ type ICloudDBInstanceDatabase interface {
|
||||
}
|
||||
|
||||
type ICloudDBInstanceAccount interface {
|
||||
ICloudResource
|
||||
GetName() string
|
||||
GetStatus() string
|
||||
GetHost() string
|
||||
|
||||
GetIDBInstanceAccountPrivileges() ([]ICloudDBInstanceAccountPrivilege, error)
|
||||
|
||||
|
||||
@@ -813,24 +813,38 @@ func syncRegionDBInstances(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
return
|
||||
}
|
||||
|
||||
syncDBInstanceNetwork(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
|
||||
syncDBInstanceParameters(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
|
||||
syncDBInstanceDatabases(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
|
||||
syncDBInstanceAccounts(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
|
||||
syncDBInstanceResource(ctx, userCred, syncResults, &localInstances[i], remoteInstances[i])
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func syncDBInstanceNetwork(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) {
|
||||
func syncDBInstanceResource(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) {
|
||||
err := syncDBInstanceNetwork(ctx, userCred, syncResults, localInstance, remoteInstance)
|
||||
if err != nil {
|
||||
log.Errorf("syncDBInstanceNetwork error: %v", err)
|
||||
}
|
||||
err = syncDBInstanceParameters(ctx, userCred, syncResults, localInstance, remoteInstance)
|
||||
if err != nil {
|
||||
log.Errorf("syncDBInstanceParameters error: %v", err)
|
||||
}
|
||||
err = syncDBInstanceDatabases(ctx, userCred, syncResults, localInstance, remoteInstance)
|
||||
if err != nil {
|
||||
log.Errorf("syncDBInstanceParameters error: %v", err)
|
||||
}
|
||||
err = syncDBInstanceAccounts(ctx, userCred, syncResults, localInstance, remoteInstance)
|
||||
if err != nil {
|
||||
log.Errorf("syncDBInstanceAccounts: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func syncDBInstanceNetwork(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) error {
|
||||
network, err := remoteInstance.GetDBNetwork()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetDBNetwork for dbinstance %s failed %s", remoteInstance.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
return
|
||||
return errors.Wrapf(err, "GetDBNetwork")
|
||||
}
|
||||
|
||||
if network == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
result := DBInstanceNetworkManager.SyncDBInstanceNetwork(ctx, userCred, localInstance, network)
|
||||
@@ -839,16 +853,15 @@ func syncDBInstanceNetwork(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
msg := result.Result()
|
||||
log.Infof("SyncDBInstanceNetwork for dbinstance %s result: %s", localInstance.Name, msg)
|
||||
if result.IsError() {
|
||||
return
|
||||
return result.AllError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncDBInstanceParameters(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) {
|
||||
func syncDBInstanceParameters(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) error {
|
||||
parameters, err := remoteInstance.GetIDBInstanceParameters()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIDBInstanceParameters for dbinstance %s failed %s", remoteInstance.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
return
|
||||
return errors.Wrapf(err, "GetIDBInstanceParameters")
|
||||
}
|
||||
|
||||
result := DBInstanceParameterManager.SyncDBInstanceParameters(ctx, userCred, localInstance, parameters)
|
||||
@@ -857,16 +870,15 @@ func syncDBInstanceParameters(ctx context.Context, userCred mcclient.TokenCreden
|
||||
msg := result.Result()
|
||||
log.Infof("SyncDBInstanceParameters for dbinstance %s result: %s", localInstance.Name, msg)
|
||||
if result.IsError() {
|
||||
return
|
||||
return result.AllError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncRegionDBInstanceBackups(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *SSyncRange) {
|
||||
func syncRegionDBInstanceBackups(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *SSyncRange) error {
|
||||
backups, err := remoteRegion.GetIDBInstanceBackups()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIDBInstanceBackups for dbinstance %s failed %s", remoteRegion.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
return
|
||||
return errors.Wrapf(err, "GetIDBInstanceBackups")
|
||||
}
|
||||
|
||||
result := DBInstanceBackupManager.SyncDBInstanceBackups(ctx, userCred, provider, nil, localRegion, backups)
|
||||
@@ -875,17 +887,16 @@ func syncRegionDBInstanceBackups(ctx context.Context, userCred mcclient.TokenCre
|
||||
msg := result.Result()
|
||||
log.Infof("SyncDBInstanceBackups for region %s result: %s", localRegion.Name, msg)
|
||||
if result.IsError() {
|
||||
return
|
||||
return result.AllError()
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func syncDBInstanceDatabases(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) {
|
||||
func syncDBInstanceDatabases(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) error {
|
||||
databases, err := remoteInstance.GetIDBInstanceDatabases()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIDBInstanceDatabases for dbinstance %s failed %s", remoteInstance.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
return
|
||||
return errors.Wrapf(err, "GetIDBInstanceDatabases")
|
||||
}
|
||||
|
||||
result := DBInstanceDatabaseManager.SyncDBInstanceDatabases(ctx, userCred, localInstance, databases)
|
||||
@@ -894,16 +905,15 @@ func syncDBInstanceDatabases(ctx context.Context, userCred mcclient.TokenCredent
|
||||
msg := result.Result()
|
||||
log.Infof("SyncDBInstanceDatabases for dbinstance %s result: %s", localInstance.Name, msg)
|
||||
if result.IsError() {
|
||||
return
|
||||
return result.AllError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncDBInstanceAccounts(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) {
|
||||
func syncDBInstanceAccounts(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localInstance *SDBInstance, remoteInstance cloudprovider.ICloudDBInstance) error {
|
||||
accounts, err := remoteInstance.GetIDBInstanceAccounts()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIDBInstanceAccounts for dbinstance %s failed %s", remoteInstance.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
return
|
||||
return errors.Wrapf(err, "GetIDBInstanceAccounts")
|
||||
}
|
||||
|
||||
localAccounts, remoteAccounts, result := DBInstanceAccountManager.SyncDBInstanceAccounts(ctx, userCred, localInstance, accounts)
|
||||
@@ -912,7 +922,7 @@ func syncDBInstanceAccounts(ctx context.Context, userCred mcclient.TokenCredenti
|
||||
msg := result.Result()
|
||||
log.Infof("SyncDBInstanceAccounts for dbinstance %s result: %s", localInstance.Name, msg)
|
||||
if result.IsError() {
|
||||
return
|
||||
return result.AllError()
|
||||
}
|
||||
|
||||
for i := 0; i < len(localAccounts); i++ {
|
||||
@@ -924,18 +934,20 @@ func syncDBInstanceAccounts(ctx context.Context, userCred mcclient.TokenCredenti
|
||||
return
|
||||
}
|
||||
|
||||
syncDBInstanceAccountPrivileges(ctx, userCred, syncResults, &localAccounts[i], remoteAccounts[i])
|
||||
err = syncDBInstanceAccountPrivileges(ctx, userCred, syncResults, &localAccounts[i], remoteAccounts[i])
|
||||
if err != nil {
|
||||
log.Errorf("syncDBInstanceAccountPrivileges error: %v", err)
|
||||
}
|
||||
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncDBInstanceAccountPrivileges(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localAccount *SDBInstanceAccount, remoteAccount cloudprovider.ICloudDBInstanceAccount) {
|
||||
func syncDBInstanceAccountPrivileges(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, localAccount *SDBInstanceAccount, remoteAccount cloudprovider.ICloudDBInstanceAccount) error {
|
||||
privileges, err := remoteAccount.GetIDBInstanceAccountPrivileges()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("GetIDBInstanceAccountPrivileges for dbinstance account %s failed %s", remoteAccount.GetName(), err)
|
||||
log.Errorf(msg)
|
||||
return
|
||||
return errors.Wrapf(err, "GetIDBInstanceAccountPrivileges for %s(%s)", localAccount.Name, localAccount.Id)
|
||||
}
|
||||
|
||||
result := DBInstancePrivilegeManager.SyncDBInstanceAccountPrivileges(ctx, userCred, localAccount, privileges)
|
||||
@@ -944,8 +956,9 @@ func syncDBInstanceAccountPrivileges(ctx context.Context, userCred mcclient.Toke
|
||||
msg := result.Result()
|
||||
log.Infof("SyncDBInstanceAccountPrivileges for account %s result: %s", localAccount.Name, msg)
|
||||
if result.IsError() {
|
||||
return
|
||||
return result.AllError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncRegionSnapshots(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *SSyncRange) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -39,7 +40,6 @@ import (
|
||||
|
||||
type SDBInstanceAccountManager struct {
|
||||
db.SStatusStandaloneResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SDBInstanceResourceBaseManager
|
||||
}
|
||||
|
||||
@@ -59,15 +59,13 @@ func init() {
|
||||
|
||||
type SDBInstanceAccount struct {
|
||||
db.SStatusStandaloneResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
|
||||
Host string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"optional" default:"%"`
|
||||
|
||||
SDBInstanceResourceBase `width:"36" charset:"ascii" name:"dbinstance_id" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
|
||||
// 数据库密码
|
||||
Secret string `width:"256" charset:"ascii" nullable:"false" list:"user" create:"optional"`
|
||||
|
||||
// RDS实例Id
|
||||
// DBInstanceId string `width:"36" charset:"ascii" name:"dbinstance_id" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
}
|
||||
|
||||
func (manager *SDBInstanceAccountManager) GetContextManagers() [][]db.IModelManager {
|
||||
@@ -224,10 +222,6 @@ func (manager *SDBInstanceAccountManager) ListItemFilter(
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SDBInstanceResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DBInstanceFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SDBInstanceResourceBaseManager.ListItemFilter")
|
||||
@@ -264,19 +258,33 @@ func (manager *SDBInstanceAccountManager) QueryDistinctExtraField(q *sqlchemy.SQ
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
type sRdsAccount struct {
|
||||
Name string
|
||||
DBInstanceId string `json:"dbinstance_id"`
|
||||
Host string
|
||||
}
|
||||
|
||||
func (self *SDBInstanceAccount) GetUniqValues() jsonutils.JSONObject {
|
||||
return jsonutils.Marshal(map[string]string{"dbinstance_id": self.DBInstanceId})
|
||||
return jsonutils.Marshal(sRdsAccount{Name: self.Name, DBInstanceId: self.DBInstanceId, Host: self.Host})
|
||||
}
|
||||
|
||||
func (manager *SDBInstanceAccountManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
|
||||
dbinstanceId, _ := data.GetString("dbinstance_id")
|
||||
return jsonutils.Marshal(map[string]string{"dbinstance_id": dbinstanceId})
|
||||
info := sRdsAccount{}
|
||||
data.Unmarshal(&info)
|
||||
return jsonutils.Marshal(info)
|
||||
}
|
||||
|
||||
func (manager *SDBInstanceAccountManager) FilterByUniqValues(q *sqlchemy.SQuery, values jsonutils.JSONObject) *sqlchemy.SQuery {
|
||||
dbinstanceId, _ := values.GetString("dbinstance_id")
|
||||
if len(dbinstanceId) > 0 {
|
||||
q = q.Equals("dbinstance_id", dbinstanceId)
|
||||
info := sRdsAccount{}
|
||||
values.Unmarshal(&info)
|
||||
if len(info.DBInstanceId) > 0 {
|
||||
q = q.Equals("dbinstance_id", info.DBInstanceId)
|
||||
}
|
||||
if len(info.Name) > 0 {
|
||||
q = q.Equals("name", info.Name)
|
||||
}
|
||||
if len(info.Host) > 0 {
|
||||
q = q.Equals("host", info.Host)
|
||||
}
|
||||
return q
|
||||
}
|
||||
@@ -612,54 +620,57 @@ func (manager *SDBInstanceAccountManager) SyncDBInstanceAccounts(ctx context.Con
|
||||
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, instance.GetOwnerId()))
|
||||
|
||||
result := compare.SyncResult{}
|
||||
localAccounts := []SDBInstanceAccount{}
|
||||
remoteAccounts := []cloudprovider.ICloudDBInstanceAccount{}
|
||||
dbAccounts, err := instance.GetDBInstanceAccounts()
|
||||
if err != nil {
|
||||
result.Error(err)
|
||||
return nil, nil, result
|
||||
}
|
||||
|
||||
localAccounts := []SDBInstanceAccount{}
|
||||
remoteAccounts := []cloudprovider.ICloudDBInstanceAccount{}
|
||||
|
||||
removed := make([]SDBInstanceAccount, 0)
|
||||
commondb := make([]SDBInstanceAccount, 0)
|
||||
commonext := make([]cloudprovider.ICloudDBInstanceAccount, 0)
|
||||
added := make([]cloudprovider.ICloudDBInstanceAccount, 0)
|
||||
if err := compare.CompareSets(dbAccounts, cloudAccounts, &removed, &commondb, &commonext, &added); err != nil {
|
||||
result.Error(err)
|
||||
return nil, nil, result
|
||||
accountMaps := map[string]SDBInstanceAccount{}
|
||||
for i := range dbAccounts {
|
||||
accountMaps[fmt.Sprintf("%s:%s", dbAccounts[i].Name, dbAccounts[i].Host)] = dbAccounts[i]
|
||||
}
|
||||
remoteMaps := map[string]cloudprovider.ICloudDBInstanceAccount{}
|
||||
for i := range cloudAccounts {
|
||||
remoteMaps[fmt.Sprintf("%s:%s", cloudAccounts[i].GetName(), cloudAccounts[i].GetHost())] = cloudAccounts[i]
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i++ {
|
||||
err := removed[i].Purge(ctx, userCred)
|
||||
for key, account := range remoteMaps {
|
||||
local, ok := accountMaps[key]
|
||||
if !ok {
|
||||
_account, err := manager.newFromCloudDBInstanceAccount(ctx, userCred, instance, account)
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
continue
|
||||
}
|
||||
result.Add()
|
||||
remoteAccounts = append(remoteAccounts, account)
|
||||
localAccounts = append(localAccounts, *_account)
|
||||
continue
|
||||
}
|
||||
err = local.SyncWithCloudDBInstanceAccount(ctx, userCred, instance, account)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
} else {
|
||||
result.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
result.Update()
|
||||
remoteAccounts = append(remoteAccounts, account)
|
||||
localAccounts = append(localAccounts, local)
|
||||
}
|
||||
|
||||
for key, account := range accountMaps {
|
||||
_, ok := remoteMaps[key]
|
||||
if !ok {
|
||||
err := account.Purge(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(commondb); i++ {
|
||||
err := commondb[i].SyncWithCloudDBInstanceAccount(ctx, userCred, instance, commonext[i])
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
} else {
|
||||
result.Update()
|
||||
localAccounts = append(localAccounts, commondb[i])
|
||||
remoteAccounts = append(remoteAccounts, commonext[i])
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(added); i++ {
|
||||
account, err := manager.newFromCloudDBInstanceAccount(ctx, userCred, instance, added[i])
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
} else {
|
||||
localAccounts = append(localAccounts, *account)
|
||||
remoteAccounts = append(remoteAccounts, added[i])
|
||||
result.Add()
|
||||
}
|
||||
}
|
||||
return localAccounts, remoteAccounts, result
|
||||
}
|
||||
|
||||
@@ -684,7 +695,6 @@ func (manager *SDBInstanceAccountManager) newFromCloudDBInstanceAccount(ctx cont
|
||||
account.Name = extAccount.GetName()
|
||||
account.DBInstanceId = instance.Id
|
||||
account.Status = extAccount.GetStatus()
|
||||
account.ExternalId = extAccount.GetGlobalId()
|
||||
|
||||
err := manager.TableSpec().Insert(ctx, &account)
|
||||
if err != nil {
|
||||
|
||||
@@ -369,6 +369,30 @@ 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")
|
||||
}
|
||||
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, "externalId: %s", backup.ExternalId)
|
||||
}
|
||||
|
||||
iRegion, err := backup.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "backup.GetIRegion")
|
||||
@@ -432,6 +456,7 @@ func (self *SDBInstanceBackup) SyncWithCloudDBInstanceBackup(
|
||||
provider *SCloudprovider,
|
||||
) error {
|
||||
_, err := db.UpdateWithLock(ctx, self, func() error {
|
||||
self.ExternalId = extBackup.GetGlobalId()
|
||||
self.Status = extBackup.GetStatus()
|
||||
self.StartTime = extBackup.GetStartTime()
|
||||
self.EndTime = extBackup.GetEndTime()
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
@@ -628,3 +629,27 @@ func (manager *SDBInstanceSkuManager) ListItemExportKeys(ctx context.Context,
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SDBInstanceSku) GetZoneInfo() (cloudprovider.SZoneInfo, error) {
|
||||
zoneInfo := cloudprovider.SZoneInfo{ZoneId: self.ZoneId}
|
||||
region := self.GetRegion()
|
||||
if region == nil {
|
||||
return zoneInfo, fmt.Errorf("empyt region for rds sku %s(%s)", self.Name, self.Id)
|
||||
}
|
||||
var cloudZoneId = func(id string) (string, error) {
|
||||
if len(id) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
_zone, err := ZoneManager.FetchById(id)
|
||||
if err != nil {
|
||||
log.Errorf("ZoneManager.FetchById(%s) error: %v", id, err)
|
||||
return "", errors.Wrapf(err, "ZoneManager.FetchById(%s)", id)
|
||||
}
|
||||
zone := _zone.(*SZone)
|
||||
return strings.TrimPrefix(zone.ExternalId, region.ExternalId+"/"), nil
|
||||
}
|
||||
zoneInfo.Zone1, _ = cloudZoneId(self.Zone1)
|
||||
zoneInfo.Zone2, _ = cloudZoneId(self.Zone2)
|
||||
zoneInfo.Zone3, _ = cloudZoneId(self.Zone3)
|
||||
return zoneInfo, nil
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ type SDBInstance struct {
|
||||
EngineVersion string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
// 套餐名称
|
||||
// example: mysql.x4.large.2c
|
||||
InstanceType string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"optional"`
|
||||
InstanceType string `width:"64" charset:"utf8" nullable:"true" list:"user" create:"optional"`
|
||||
|
||||
// 维护时间
|
||||
MaintainTime string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"optional"`
|
||||
@@ -666,7 +666,11 @@ func (self *SDBInstance) GetIDBInstance() (cloudprovider.ICloudDBInstance, error
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "self.GetIRegion")
|
||||
}
|
||||
return iregion.GetIDBInstanceById(self.ExternalId)
|
||||
iRds, err := iregion.GetIDBInstanceById(self.ExternalId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetIDBInstanceById(%s)", self.ExternalId)
|
||||
}
|
||||
return iRds, nil
|
||||
}
|
||||
|
||||
func (self *SDBInstance) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) (jsonutils.JSONObject, error) {
|
||||
@@ -1413,26 +1417,19 @@ func (self *SDBInstance) GetAvailableZoneIds() ([]string, error) {
|
||||
}
|
||||
|
||||
func (self *SDBInstance) GetAvailableInstanceTypes() ([]cloudprovider.SInstanceType, error) {
|
||||
instanceTypes := map[string]cloudprovider.SInstanceType{}
|
||||
instanceTypes := []cloudprovider.SInstanceType{}
|
||||
skus, err := self.GetAvailableDBInstanceSkus()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "self.GetAvailableDBInstanceSkus")
|
||||
}
|
||||
|
||||
for _, sku := range skus {
|
||||
if instanceType, ok := instanceTypes[sku.Name]; !ok {
|
||||
instanceTypes[sku.Name] = cloudprovider.SInstanceType{InstanceType: sku.Name, ZoneIds: []string{sku.ZoneId}}
|
||||
} else if !utils.IsInStringArray(sku.ZoneId, instanceType.ZoneIds) {
|
||||
instanceType.ZoneIds = append(instanceType.ZoneIds, sku.ZoneId)
|
||||
}
|
||||
instanceType := cloudprovider.SInstanceType{}
|
||||
instanceType.InstanceType = sku.Name
|
||||
instanceType.SZoneInfo, _ = sku.GetZoneInfo()
|
||||
instanceTypes = append(instanceTypes, instanceType)
|
||||
}
|
||||
|
||||
result := []cloudprovider.SInstanceType{}
|
||||
for _, instanceType := range instanceTypes {
|
||||
result = append(result, instanceType)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return instanceTypes, nil
|
||||
}
|
||||
|
||||
func (self *SDBInstance) setZoneInfo() error {
|
||||
@@ -1491,8 +1488,18 @@ func (self *SDBInstance) SetZoneIds(extInstance cloudprovider.ICloudDBInstance)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SDBInstance) SyncAllWithCloudDBInstance(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extInstance cloudprovider.ICloudDBInstance) error {
|
||||
err := self.SyncWithCloudDBInstance(ctx, userCred, provider, extInstance)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SyncWithCloudDBInstance")
|
||||
}
|
||||
syncDBInstanceResource(ctx, userCred, SSyncResultSet{}, self, extInstance)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDBInstance) SyncWithCloudDBInstance(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extInstance cloudprovider.ICloudDBInstance) error {
|
||||
diff, err := db.UpdateWithLock(ctx, self, func() error {
|
||||
self.ExternalId = extInstance.GetGlobalId()
|
||||
self.Engine = extInstance.GetEngine()
|
||||
self.EngineVersion = extInstance.GetEngineVersion()
|
||||
self.InstanceType = extInstance.GetInstanceType()
|
||||
|
||||
@@ -219,7 +219,6 @@ func (self *SGoogleRegionDriver) InitDBInstanceUser(ctx context.Context, instanc
|
||||
account.DBInstanceId = instance.Id
|
||||
account.Name = user
|
||||
account.Status = api.DBINSTANCE_USER_AVAILABLE
|
||||
account.ExternalId = user
|
||||
account.SetModelManager(models.DBInstanceAccountManager, &account)
|
||||
err := models.DBInstanceAccountManager.TableSpec().Insert(ctx, &account)
|
||||
if err != nil {
|
||||
|
||||
@@ -2187,7 +2187,6 @@ func (self *SHuaWeiRegionDriver) InitDBInstanceUser(ctx context.Context, instanc
|
||||
account.DBInstanceId = instance.Id
|
||||
account.Name = user
|
||||
account.Status = api.DBINSTANCE_USER_AVAILABLE
|
||||
account.ExternalId = user
|
||||
account.SetModelManager(models.DBInstanceAccountManager, &account)
|
||||
err := models.DBInstanceAccountManager.TableSpec().Insert(ctx, &account)
|
||||
if err != nil {
|
||||
|
||||
@@ -1610,7 +1610,6 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstance(ctx cont
|
||||
Description: dbinstance.Description,
|
||||
StorageType: dbinstance.StorageType,
|
||||
DiskSizeGB: dbinstance.DiskSizeGB,
|
||||
InstanceType: dbinstance.InstanceType,
|
||||
VcpuCount: dbinstance.VcpuCount,
|
||||
VmemSizeMb: dbinstance.VmemSizeMb,
|
||||
VpcId: vpc.ExternalId,
|
||||
@@ -1629,12 +1628,6 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstance(ctx cont
|
||||
log.Errorf("failed to sync project %s for create %s rds %s error: %v", dbinstance.ProjectId, _cloudprovider.Provider, dbinstance.Name, err)
|
||||
}
|
||||
|
||||
if len(dbinstance.InstanceType) > 0 {
|
||||
desc.ZoneIds, _ = dbinstance.GetAvailableZoneIds()
|
||||
} else {
|
||||
desc.InstanceTypes, _ = dbinstance.GetAvailableInstanceTypes()
|
||||
}
|
||||
|
||||
region := dbinstance.GetRegion()
|
||||
|
||||
err = region.GetDriver().InitDBInstanceUser(ctx, dbinstance, task, &desc)
|
||||
@@ -1673,49 +1666,46 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstance(ctx cont
|
||||
desc.MasterInstanceId = master.ExternalId
|
||||
}
|
||||
|
||||
log.Debugf("create dbinstance params: %s", jsonutils.Marshal(desc).String())
|
||||
|
||||
idbinstance, err := iregion.CreateIDBInstance(&desc)
|
||||
if idbinstance != nil { //避免创建失败后,删除本地的未能同步删除云上失败的RDS
|
||||
db.SetExternalId(dbinstance, userCred, idbinstance.GetGlobalId())
|
||||
}
|
||||
instanceTypes, err := dbinstance.GetAvailableInstanceTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "GetAvailableInstanceTypes")
|
||||
}
|
||||
if len(instanceTypes) == 0 {
|
||||
return nil, fmt.Errorf("no avaiable sku for create")
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(idbinstance, api.DBINSTANCE_RUNNING, time.Second*5, time.Hour*1)
|
||||
var createFunc = func() (cloudprovider.ICloudDBInstance, error) {
|
||||
errMsgs := []string{}
|
||||
for i := range instanceTypes {
|
||||
desc.SInstanceType = instanceTypes[i]
|
||||
log.Debugf("create dbinstance params: %s", jsonutils.Marshal(desc).String())
|
||||
|
||||
iRds, err := iregion.CreateIDBInstance(&desc)
|
||||
if err != nil {
|
||||
errMsgs = append(errMsgs, err.Error())
|
||||
continue
|
||||
}
|
||||
return iRds, nil
|
||||
}
|
||||
if len(errMsgs) > 0 {
|
||||
return nil, fmt.Errorf(strings.Join(errMsgs, "\n"))
|
||||
}
|
||||
return nil, fmt.Errorf("no avaiable skus %s(%dC%d) for create", dbinstance.InstanceType, desc.VcpuCount, desc.VmemSizeMb)
|
||||
}
|
||||
|
||||
iRds, err := createFunc()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "create")
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*5, time.Hour*1)
|
||||
if err != nil {
|
||||
log.Errorf("timeout for waiting dbinstance running error: %v", err)
|
||||
}
|
||||
|
||||
dbinstance.SyncWithCloudDBInstance(ctx, userCred, dbinstance.GetCloudprovider(), idbinstance)
|
||||
|
||||
network, err := idbinstance.GetDBNetwork()
|
||||
err = dbinstance.SyncAllWithCloudDBInstance(ctx, userCred, dbinstance.GetCloudprovider(), iRds)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get get network for dbinstance %s(%s) error: %v", dbinstance.Name, dbinstance.Id, err)
|
||||
} else {
|
||||
models.DBInstanceNetworkManager.SyncDBInstanceNetwork(ctx, userCred, dbinstance, network)
|
||||
}
|
||||
|
||||
parameters, err := idbinstance.GetIDBInstanceParameters()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get parameters for dbinstance %s(%s) error: %v", dbinstance.Name, dbinstance.Id, err)
|
||||
} else {
|
||||
models.DBInstanceParameterManager.SyncDBInstanceParameters(ctx, userCred, dbinstance, parameters)
|
||||
}
|
||||
|
||||
backups, err := idbinstance.GetIDBInstanceBackups()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get backups for dbinstance %s(%s) error: %v", dbinstance.Name, dbinstance.Id, err)
|
||||
} else {
|
||||
models.DBInstanceBackupManager.SyncDBInstanceBackups(ctx, userCred, dbinstance.GetCloudprovider(), dbinstance, dbinstance.GetRegion(), backups)
|
||||
}
|
||||
|
||||
databases, err := idbinstance.GetIDBInstanceDatabases()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get databases for databases %s(%s) error: %v", dbinstance.Name, dbinstance.Id, err)
|
||||
} else {
|
||||
models.DBInstanceDatabaseManager.SyncDBInstanceDatabases(ctx, userCred, dbinstance, databases)
|
||||
log.Errorf("SyncAllWithCloudDBInstance error: %v", err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
@@ -2223,37 +2213,36 @@ func (self *SManagedVirtualizationRegionDriver) RequestChangeDBInstanceConfig(ct
|
||||
instance.StorageType = input.StorageType
|
||||
}
|
||||
|
||||
conf := &cloudprovider.SManagedDBInstanceChangeConfig{
|
||||
conf := cloudprovider.SManagedDBInstanceChangeConfig{
|
||||
DiskSizeGB: input.DiskSizeGB,
|
||||
StorageType: instance.StorageType,
|
||||
}
|
||||
|
||||
instanceTypes := []string{}
|
||||
opts := []cloudprovider.SManagedDBInstanceChangeConfig{}
|
||||
|
||||
if len(input.InstanceType) > 0 {
|
||||
conf.InstanceType = input.InstanceType
|
||||
} else if input.VCpuCount == 0 && input.VmemSizeMb == 0 {
|
||||
conf.InstanceType = instance.InstanceType
|
||||
} else {
|
||||
instance.InstanceType = ""
|
||||
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 _, sku := range skus {
|
||||
instanceTypes = append(instanceTypes, sku.Name)
|
||||
for i := range skus {
|
||||
conf.InstanceType = skus[i].Name
|
||||
conf.VcpuCount = skus[i].VcpuCount
|
||||
conf.VmemSizeMb = skus[i].VmemSizeMb
|
||||
opts = append(opts, conf)
|
||||
}
|
||||
}
|
||||
|
||||
if len(conf.InstanceType) == 0 && len(instanceTypes) == 0 {
|
||||
return nil, fmt.Errorf("No available dbinstance sku for change config")
|
||||
} else {
|
||||
conf.InstanceType = instance.InstanceType
|
||||
conf.VcpuCount = instance.VcpuCount
|
||||
conf.VmemSizeMb = instance.VmemSizeMb
|
||||
opts = append(opts, conf)
|
||||
}
|
||||
|
||||
iRds, err := instance.GetIDBInstance()
|
||||
@@ -2261,29 +2250,38 @@ func (self *SManagedVirtualizationRegionDriver) RequestChangeDBInstanceConfig(ct
|
||||
return nil, errors.Wrap(err, "instance.GetIDBInstance")
|
||||
}
|
||||
|
||||
log.Infof("change config: %s", jsonutils.Marshal(conf).String())
|
||||
|
||||
if len(conf.InstanceType) > 0 {
|
||||
err = iRds.ChangeConfig(ctx, conf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "iRds.ChangeConfig(%s)", conf.InstanceType)
|
||||
}
|
||||
} else {
|
||||
for _, instanceType := range instanceTypes {
|
||||
conf.InstanceType = instanceType
|
||||
log.Infof("try change instance type to %s", instance.InstanceType)
|
||||
err = iRds.ChangeConfig(ctx, conf)
|
||||
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 {
|
||||
log.Warningf("change failed: %v try another", err)
|
||||
errMsgs = append(errMsgs, err.Error())
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil, fmt.Errorf("no available dbinstance sku to change")
|
||||
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
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*10, time.Minute*40)
|
||||
if err != nil {
|
||||
log.Errorf("failed to wait rds %s(%s) status running", instance.Name, instance.Id)
|
||||
return nil, errors.Wrapf(err, "cloudprovider.WaitStatus")
|
||||
}
|
||||
|
||||
err = iRds.Refresh()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "iRds.Refresh")
|
||||
}
|
||||
|
||||
_, err = db.Update(instance, func() error {
|
||||
instance.InstanceType = iRds.GetInstanceType()
|
||||
instance.Category = iRds.GetCategory()
|
||||
@@ -2308,11 +2306,6 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceBackup(ct
|
||||
return nil, errors.Wrap(err, "instance.GetIDBInstance")
|
||||
}
|
||||
|
||||
iRegion, err := backup.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "backup.GetIRegion")
|
||||
}
|
||||
|
||||
desc := &cloudprovider.SDBInstanceBackupCreateConfig{
|
||||
Name: backup.Name,
|
||||
}
|
||||
@@ -2326,11 +2319,14 @@ func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceBackup(ct
|
||||
return nil, errors.Wrap(err, "iRds.CreateBackup")
|
||||
}
|
||||
|
||||
db.SetExternalId(backup, userCred, backupId)
|
||||
|
||||
iBackup, err := iRegion.GetIDBInstanceBackupById(backupId)
|
||||
err = db.SetExternalId(backup, userCred, backupId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "iRegion.GetIDBInstanceBackupById(%s)", backupId)
|
||||
return nil, errors.Wrapf(err, "db.SetExternalId")
|
||||
}
|
||||
|
||||
iBackup, err := backup.GetIDBInstanceBackup()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "backup.GetIDBInstanceBackup")
|
||||
}
|
||||
|
||||
_, err = db.Update(backup, func() error {
|
||||
|
||||
@@ -1358,3 +1358,57 @@ func (self *SQcloudRegionDriver) RequestSyncLoadbalancerListener(ctx context.Con
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) InitDBInstanceUser(ctx context.Context, instance *models.SDBInstance, task taskman.ITask, desc *cloudprovider.SManagedDBInstanceCreateConfig) error {
|
||||
user := "root"
|
||||
account := models.SDBInstanceAccount{}
|
||||
account.DBInstanceId = instance.Id
|
||||
account.Name = user
|
||||
account.Host = "%"
|
||||
if instance.Engine == api.DBINSTANCE_TYPE_MYSQL && instance.Category == api.QCLOUD_DBINSTANCE_CATEGORY_BASIC {
|
||||
account.Host = "localhost"
|
||||
}
|
||||
account.Status = api.DBINSTANCE_USER_AVAILABLE
|
||||
account.SetModelManager(models.DBInstanceAccountManager, &account)
|
||||
err := models.DBInstanceAccountManager.TableSpec().Insert(ctx, &account)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Insert")
|
||||
}
|
||||
return account.SetPassword(desc.Password)
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) IsSupportedDBInstance() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) IsDBInstanceNeedSecgroup() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceBackupCreateInput) (api.DBInstanceBackupCreateInput, error) {
|
||||
switch instance.Engine {
|
||||
case api.DBINSTANCE_TYPE_MYSQL:
|
||||
if instance.Category == api.QCLOUD_DBINSTANCE_CATEGORY_BASIC {
|
||||
return input, httperrors.NewNotSupportedError("Qcloud Basic MySQL instance not support create backup")
|
||||
}
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceDatabaseCreateInput) (api.DBInstanceDatabaseCreateInput, error) {
|
||||
return input, httperrors.NewNotSupportedError("Not support create Qcloud databases")
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) ValidateDBInstanceAccountPrivilege(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, account string, privilege string) error {
|
||||
switch privilege {
|
||||
case api.DATABASE_PRIVILEGE_RW:
|
||||
case api.DATABASE_PRIVILEGE_R:
|
||||
default:
|
||||
return httperrors.NewInputParameterError("Unknown privilege %s", privilege)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ func (self *DBInstanceAccountCreateTask) CreateDBInstanceAccount(ctx context.Con
|
||||
|
||||
desc := &cloudprovider.SDBInstanceAccountCreateConfig{
|
||||
Name: account.Name,
|
||||
Host: account.Host,
|
||||
}
|
||||
desc.Password, _ = account.GetPassword()
|
||||
|
||||
@@ -85,7 +86,7 @@ func (self *DBInstanceAccountCreateTask) CreateDBInstanceAccount(ctx context.Con
|
||||
|
||||
var iAccount cloudprovider.ICloudDBInstanceAccount = nil
|
||||
for i := range iAccounts {
|
||||
if iAccounts[i].GetName() == account.Name {
|
||||
if iAccounts[i].GetName() == account.Name && iAccounts[i].GetHost() == account.Host {
|
||||
iAccount = iAccounts[i]
|
||||
break
|
||||
}
|
||||
@@ -100,7 +101,7 @@ func (self *DBInstanceAccountCreateTask) CreateDBInstanceAccount(ctx context.Con
|
||||
return
|
||||
}
|
||||
|
||||
db.SetExternalId(account, self.UserCred, iAccount.GetGlobalId())
|
||||
//db.SetExternalId(account, self.UserCred, iAccount.GetGlobalId())
|
||||
|
||||
input := api.DBInstanceAccountCreateInput{}
|
||||
self.GetParams().Unmarshal(&input)
|
||||
|
||||
@@ -66,7 +66,7 @@ func (self *DBInstanceAccountRevokePrivilegeTask) OnInit(ctx context.Context, ob
|
||||
|
||||
var iAccount cloudprovider.ICloudDBInstanceAccount = nil
|
||||
for _, ac := range accounts {
|
||||
if ac.GetName() == account.Name {
|
||||
if ac.GetName() == account.Name && ac.GetHost() == account.Host {
|
||||
iAccount = ac
|
||||
break
|
||||
}
|
||||
|
||||
@@ -49,15 +49,9 @@ func (self *DBInstanceBackupDeleteTask) OnInit(ctx context.Context, obj db.IStan
|
||||
}
|
||||
|
||||
func (self *DBInstanceBackupDeleteTask) DeleteDBInstanceBackup(ctx context.Context, backup *models.SDBInstanceBackup) {
|
||||
iRegion, err := backup.GetIRegion()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, backup, errors.Wrap(err, "backup.GetIRegion"))
|
||||
return
|
||||
}
|
||||
|
||||
iBackup, err := iRegion.GetIDBInstanceBackupById(backup.ExternalId)
|
||||
if err != nil && err != cloudprovider.ErrNotFound {
|
||||
self.taskFailed(ctx, backup, errors.Wrap(err, "iRegion.GetIDBInstanceBackupById"))
|
||||
iBackup, err := backup.GetIDBInstanceBackup()
|
||||
if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
self.taskFailed(ctx, backup, errors.Wrap(err, "backup.GetIDBInstanceBackup"))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -40,7 +39,7 @@ func (self *DBInstanceCreateTask) taskFailed(ctx context.Context, dbinstance *mo
|
||||
dbinstance.SetStatus(self.UserCred, api.DBINSTANCE_CREATE_FAILED, err.Error())
|
||||
db.OpsLog.LogEvent(dbinstance, db.ACT_CREATE, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_CREATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.Marshal(err))
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *DBInstanceCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
@@ -62,35 +61,6 @@ func (self *DBInstanceCreateTask) OnCreateDBInstanceComplete(ctx context.Context
|
||||
dbinstance := obj.(*models.SDBInstance)
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_CREATE, nil, self.UserCred, true)
|
||||
|
||||
accounts, err := dbinstance.GetDBInstanceAccounts()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get dbinstance %s account error: %v", dbinstance.Name, err)
|
||||
}
|
||||
|
||||
if len(accounts) > 0 {
|
||||
iRds, err := dbinstance.GetIDBInstance()
|
||||
if err != nil {
|
||||
log.Errorf("failed to found dbinstance %s error: %v", dbinstance.Name, err)
|
||||
} else {
|
||||
iAccounts, err := iRds.GetIDBInstanceAccounts()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get accounts from cloud dbinstance %s error: %v", dbinstance.Name, err)
|
||||
}
|
||||
externalIds := map[string]string{}
|
||||
for _, iAccount := range iAccounts {
|
||||
externalIds[iAccount.GetName()] = iAccount.GetGlobalId()
|
||||
}
|
||||
for i := range accounts {
|
||||
externalId, ok := externalIds[accounts[i].Name]
|
||||
if !ok {
|
||||
log.Errorf("failed to get dbinstance account %s from cloud dbinstance for set externalId", accounts[i].Name)
|
||||
} else {
|
||||
db.SetExternalId(&accounts[i], self.UserCred, externalId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.SetStage("OnSyncDBInstanceStatusComplete", nil)
|
||||
models.StartResourceSyncStatusTask(ctx, self.UserCred, dbinstance, "DBInstanceSyncStatusTask", self.GetTaskId())
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func (self *DBInstancePublicConnectionTask) getAction() string {
|
||||
func (self *DBInstancePublicConnectionTask) taskFailed(ctx context.Context, dbinstance *models.SDBInstance, err error) {
|
||||
dbinstance.SetStatus(self.UserCred, api.DBINSTANCE_FAILE, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, self.getAction(), err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.Marshal(err))
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *DBInstancePublicConnectionTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
@@ -63,7 +63,9 @@ func (self *DBInstancePublicConnectionTask) DBInstancePublicConnectionOperation(
|
||||
return
|
||||
}
|
||||
|
||||
if isOpen, _ := self.GetParams().Bool("open"); isOpen {
|
||||
isOpen := jsonutils.QueryBoolean(self.GetParams(), "open", false)
|
||||
|
||||
if isOpen {
|
||||
err = idbinstance.OpenPublicConnection()
|
||||
} else {
|
||||
err = idbinstance.ClosePublicConnection()
|
||||
@@ -73,14 +75,27 @@ func (self *DBInstancePublicConnectionTask) DBInstancePublicConnectionOperation(
|
||||
return
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(idbinstance, api.DBINSTANCE_RUNNING, 10*time.Second, time.Minute*30)
|
||||
connectionStr := ""
|
||||
|
||||
err = cloudprovider.Wait(time.Second*10, time.Minute*5, func() (bool, error) {
|
||||
iRds, err := instance.GetIDBInstance()
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "GetIDBInstance")
|
||||
}
|
||||
connectionStr = iRds.GetConnectionStr()
|
||||
if (isOpen && len(connectionStr) > 0) || (!isOpen && len(connectionStr) == 0) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, instance, errors.Wrap(err, "cloudprovider.WaitStatus"))
|
||||
self.taskFailed(ctx, instance, errors.Wrapf(err, "cloudprovider.Wait"))
|
||||
return
|
||||
}
|
||||
|
||||
_, err = db.Update(instance, func() error {
|
||||
instance.ConnectionStr = idbinstance.GetConnectionStr()
|
||||
instance.ConnectionStr = connectionStr
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ func (self *DBInstanceSyncStatusTask) taskFailed(ctx context.Context, dbinstance
|
||||
dbinstance.SetStatus(self.UserCred, api.DBINSTANCE_UNKNOWN, err.Error())
|
||||
db.OpsLog.LogEvent(dbinstance, db.ACT_SYNC_STATUS, err, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, dbinstance, logclient.ACT_SYNC_STATUS, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.Marshal(err))
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *DBInstanceSyncStatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
|
||||
@@ -53,7 +53,7 @@ func (self *DBInstanceSyncTask) SyncDBInstance(ctx context.Context, dbinstance *
|
||||
self.taskFailed(ctx, dbinstance, errors.Wrapf(err, "dbinstance.GetIDBInstance"))
|
||||
return
|
||||
}
|
||||
err = dbinstance.SyncWithCloudDBInstance(ctx, self.UserCred, dbinstance.GetCloudprovider(), idbinstance)
|
||||
err = dbinstance.SyncAllWithCloudDBInstance(ctx, self.UserCred, dbinstance.GetCloudprovider(), idbinstance)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, dbinstance, errors.Wrapf(err, "dbinstance.GetIDBInstance"))
|
||||
return
|
||||
|
||||
@@ -26,7 +26,7 @@ var (
|
||||
|
||||
func init() {
|
||||
DBInstanceSkus = DBInstanceSkusManager{NewComputeManager("dbinstance_sku", "dbinstance_skus",
|
||||
[]string{"Id", "Name", "Engine", "Engine_Version", "Category", "Storage_Type", "Status", "Enabled"},
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&DBInstanceSkus)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// 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 "yunion.io/x/jsonutils"
|
||||
|
||||
type DBInstanceSkuListOption struct {
|
||||
BaseListOptions
|
||||
Engine string
|
||||
EngineVersion string
|
||||
Category string
|
||||
StorageType string
|
||||
Cloudregion string
|
||||
VcpuCount *int
|
||||
VmemSizeMb *int
|
||||
}
|
||||
|
||||
func (opts *DBInstanceSkuListOption) Params() (jsonutils.JSONObject, error) {
|
||||
return ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type DBInstanceSkuIdOption struct {
|
||||
ID string `help:"DBInstance Id or name"`
|
||||
}
|
||||
|
||||
func (opts *DBInstanceSkuIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (opts *DBInstanceSkuIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
@@ -604,17 +604,18 @@ func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceC
|
||||
"RegionId": region.RegionId,
|
||||
"Engine": desc.Engine,
|
||||
"EngineVersion": desc.EngineVersion,
|
||||
"DBInstanceClass": desc.InstanceType,
|
||||
"DBInstanceStorage": fmt.Sprintf("%d", desc.DiskSizeGB),
|
||||
"DBInstanceNetType": "Intranet",
|
||||
"PayType": "Postpaid",
|
||||
"SecurityIPList": "0.0.0.0/0",
|
||||
"DBInstanceDescription": desc.Name,
|
||||
"ClientToken": utils.GenRequestId(20),
|
||||
"InstanceNetworkType": "VPC",
|
||||
"VPCId": desc.VpcId,
|
||||
"VSwitchId": desc.NetworkId,
|
||||
"DBInstanceStorageType": desc.StorageType,
|
||||
"DBInstanceClass": desc.InstanceType,
|
||||
"ZoneId": desc.ZoneId,
|
||||
"ClientToken": utils.GenRequestId(20),
|
||||
}
|
||||
switch desc.Category {
|
||||
case api.ALIYUN_DBINSTANCE_CATEGORY_HA:
|
||||
@@ -651,43 +652,9 @@ func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceC
|
||||
params["DBInstanceId"] = desc.MasterInstanceId
|
||||
}
|
||||
|
||||
var err error
|
||||
var resp jsonutils.JSONObject
|
||||
if len(desc.InstanceType) > 0 {
|
||||
params["DBInstanceClass"] = desc.InstanceType
|
||||
for _, zoneId := range desc.ZoneIds {
|
||||
params["ZoneId"] = zoneId
|
||||
resp, err = region.rdsRequest(action, params)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(desc.ZoneIds) == 0 {
|
||||
resp, err = region.rdsRequest(action, params)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "region.rdsRequest.%s", action)
|
||||
}
|
||||
} else {
|
||||
for _, spec := range desc.InstanceTypes {
|
||||
params["DBInstanceClass"] = spec.InstanceType
|
||||
for _, zoneId := range spec.ZoneIds {
|
||||
params["ZoneId"] = zoneId
|
||||
resp, err = region.rdsRequest(action, params)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "region.rdsRequest.%s", action)
|
||||
}
|
||||
if resp == nil {
|
||||
return nil, fmt.Errorf("dbinstance type %dC%dMB not avaiable", desc.VcpuCount, desc.VmemSizeMb)
|
||||
}
|
||||
resp, err := region.rdsRequest(action, params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "rdsRequest")
|
||||
}
|
||||
instanceId, err := resp.GetString("DBInstanceId")
|
||||
if err != nil {
|
||||
|
||||
@@ -41,14 +41,6 @@ type SDBInstanceAccount struct {
|
||||
PrivExceeded string
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetId() string {
|
||||
return account.AccountName
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetGlobalId() string {
|
||||
return account.AccountName
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetName() string {
|
||||
return account.AccountName
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ type SDatabasePrivilege struct {
|
||||
}
|
||||
|
||||
func (privilege *SDatabasePrivilege) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", privilege.account.GetGlobalId(), privilege.DBName)
|
||||
return fmt.Sprintf("%s/%s", privilege.account.GetName(), privilege.DBName)
|
||||
}
|
||||
|
||||
func (privilege *SDatabasePrivilege) GetPrivilege() string {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
@@ -26,18 +25,6 @@ type SDBInstanceAccount struct {
|
||||
AccountName string
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetId() string {
|
||||
return account.AccountName
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetGlobalId() string {
|
||||
return account.AccountName
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetName() string {
|
||||
return account.AccountName
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetStatus() string {
|
||||
return api.DBINSTANCE_USER_AVAILABLE
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ package multicloud
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SDBInstanceAccountBase struct {
|
||||
SResourceBase
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccountBase) GetIDBInstanceAccountPrivileges() ([]cloudprovider.ICloudDBInstanceAccountPrivilege, error) {
|
||||
@@ -45,6 +45,14 @@ func (account *SDBInstanceAccountBase) Delete() error {
|
||||
return errors.Wrapf(cloudprovider.ErrNotImplemented, "Delete")
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccountBase) GetHost() string {
|
||||
return "%"
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccountBase) GetStatus() string {
|
||||
return api.DBINSTANCE_USER_AVAILABLE
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccountBase) ResetPassword(password string) error {
|
||||
return errors.Wrapf(cloudprovider.ErrNotImplemented, "ResetPassword")
|
||||
}
|
||||
|
||||
@@ -625,45 +625,9 @@ func (region *SRegion) CreateDBInstance(desc *cloudprovider.SManagedDBInstanceCr
|
||||
if _, ok := EngineVersions[databaseVersion]; !ok {
|
||||
return nil, fmt.Errorf("Unsupport %s version %s", desc.Engine, desc.EngineVersion)
|
||||
}
|
||||
var err error
|
||||
var rds *SDBInstance = nil
|
||||
if len(desc.InstanceType) > 0 {
|
||||
if len(desc.ZoneIds) == 0 {
|
||||
desc.ZoneIds = append(desc.ZoneIds, "")
|
||||
}
|
||||
for _, zoneId := range desc.ZoneIds {
|
||||
rds, err = region.CreateRds(desc.Name, desc.Engine, databaseVersion, desc.Category, desc.InstanceType, desc.StorageType, desc.DiskSizeGB, desc.VpcId, zoneId, desc.Password)
|
||||
if err == nil {
|
||||
break
|
||||
} else {
|
||||
log.Errorf("failed to create dbinstance %s at %s error: %v", desc.Name, zoneId, err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CreateRds")
|
||||
}
|
||||
} else if len(desc.InstanceTypes) > 0 {
|
||||
for _, spec := range desc.InstanceTypes {
|
||||
if len(spec.ZoneIds) == 0 {
|
||||
desc.ZoneIds = append(desc.ZoneIds, "")
|
||||
}
|
||||
for _, zoneId := range spec.ZoneIds {
|
||||
rds, err = region.CreateRds(desc.Name, desc.Engine, databaseVersion, desc.Category, desc.InstanceType, desc.StorageType, desc.DiskSizeGB, desc.VpcId, zoneId, desc.Password)
|
||||
if err == nil {
|
||||
break
|
||||
} else {
|
||||
log.Errorf("failed to create dbinstance %s at %s error: %v", desc.Name, zoneId, err)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CreateRds")
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("Missing instance type info")
|
||||
rds, err := region.CreateRds(desc.Name, desc.Engine, databaseVersion, desc.Category, desc.InstanceType, desc.StorageType, desc.DiskSizeGB, desc.VpcId, desc.ZoneId, desc.Password)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateRds")
|
||||
}
|
||||
return rds, nil
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SSqlserverUserDetails struct {
|
||||
@@ -30,6 +30,7 @@ type SSqlserverUserDetails struct {
|
||||
}
|
||||
|
||||
type SDBInstanceAccount struct {
|
||||
multicloud.SDBInstanceAccountBase
|
||||
rds *SDBInstance
|
||||
|
||||
Kind string
|
||||
@@ -71,30 +72,14 @@ func (account *SDBInstanceAccount) Delete() error {
|
||||
return account.rds.region.DeleteDBInstanceAccount(account.rds.Name, account.Name, account.Host)
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetGlobalId() string {
|
||||
return account.Name
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetId() string {
|
||||
return account.SelfLink
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
func (account *SDBInstanceAccount) GetHost() string {
|
||||
return account.Host
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetName() string {
|
||||
return account.Name
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetStatus() string {
|
||||
return api.DBINSTANCE_USER_AVAILABLE
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) Refresh() error {
|
||||
_account, err := account.rds.region.GetDBInstanceAccount(account.SelfLink)
|
||||
if err != nil {
|
||||
|
||||
@@ -469,17 +469,7 @@ func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceC
|
||||
"replication_mode": "sync",
|
||||
}
|
||||
}
|
||||
if len(desc.ZoneIds) == 0 {
|
||||
for _, masterZoneId := range zoneIds {
|
||||
for _, slaveZoneId := range zoneIds {
|
||||
desc.ZoneIds = append(desc.ZoneIds, fmt.Sprintf("%s,%s", masterZoneId, slaveZoneId))
|
||||
}
|
||||
}
|
||||
}
|
||||
case api.HUAWEI_DBINSTANCE_CATEGORY_SINGLE:
|
||||
if len(desc.ZoneIds) == 0 {
|
||||
desc.ZoneIds = zoneIds
|
||||
}
|
||||
case api.HUAWEI_DBINSTANCE_CATEGORY_REPLICA:
|
||||
}
|
||||
|
||||
@@ -497,42 +487,11 @@ func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceC
|
||||
"is_auto_renew": false,
|
||||
}
|
||||
}
|
||||
var resp jsonutils.JSONObject = nil
|
||||
|
||||
if len(desc.InstanceType) > 0 {
|
||||
params["flavor_ref"] = desc.InstanceType
|
||||
for _, zoneId := range desc.ZoneIds {
|
||||
params["availability_zone"] = zoneId
|
||||
resp, err = region.ecsClient.DBInstance.Create(jsonutils.Marshal(params))
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Debugf("params: %s", jsonutils.Marshal(params).PrettyString())
|
||||
return nil, errors.Wrap(err, "DBInstance.Create")
|
||||
}
|
||||
} else {
|
||||
for _, spec := range desc.InstanceTypes {
|
||||
params["flavor_ref"] = spec.InstanceType
|
||||
for _, zoneId := range spec.ZoneIds {
|
||||
params["availability_zone"] = zoneId
|
||||
resp, err = region.ecsClient.DBInstance.Create(jsonutils.Marshal(params))
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Debugf("params: %s", jsonutils.Marshal(params).PrettyString())
|
||||
return nil, errors.Wrap(err, "region.ecsClient.DBInstance.Create")
|
||||
}
|
||||
if resp == nil {
|
||||
return nil, fmt.Errorf("dbinstance type %dC%dMB not avaiable", desc.VcpuCount, desc.VmemSizeMb)
|
||||
}
|
||||
params["flavor_ref"] = desc.InstanceType
|
||||
params["availability_zone"] = desc.ZoneId
|
||||
resp, err := region.ecsClient.DBInstance.Create(jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Create")
|
||||
}
|
||||
|
||||
instance := &SDBInstance{region: region}
|
||||
|
||||
@@ -30,15 +30,6 @@ type SDBInstanceAccount struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetId() string {
|
||||
return account.Name
|
||||
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetGlobalId() string {
|
||||
return account.Name
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetName() string {
|
||||
return account.Name
|
||||
}
|
||||
@@ -51,10 +42,6 @@ func (region *SRegion) DeleteDBInstanceAccount(instanceId string, account string
|
||||
return DoDeleteWithSpec(region.ecsClient.DBInstance.DeleteInContextWithSpec, nil, instanceId, fmt.Sprintf("db_user/%s", account), nil, nil)
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetStatus() string {
|
||||
return api.DBINSTANCE_USER_AVAILABLE
|
||||
}
|
||||
|
||||
func (account *SDBInstanceAccount) GetIDBInstanceAccountPrivileges() ([]cloudprovider.ICloudDBInstanceAccountPrivilege, error) {
|
||||
privileges, err := account.instance.region.GetDBInstancePrivvileges(account.instance.Id, account.Name)
|
||||
if err != nil {
|
||||
|
||||
@@ -28,7 +28,7 @@ type SDatabasePrivilege struct {
|
||||
}
|
||||
|
||||
func (privilege *SDatabasePrivilege) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", privilege.account.GetGlobalId(), privilege.Name)
|
||||
return fmt.Sprintf("%s/%s", privilege.account.Name, privilege.Name)
|
||||
}
|
||||
|
||||
func (privilege *SDatabasePrivilege) GetPrivilege() string {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
func (self *SRegion) GetIDBInstances() ([]cloudprovider.ICloudDBInstance, error) {
|
||||
ret := []cloudprovider.ICloudDBInstance{}
|
||||
mysql := []SMySQLInstance{}
|
||||
for {
|
||||
part, total, err := self.ListMySQLInstances([]string{}, len(mysql), 50)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListMySQLInstances")
|
||||
}
|
||||
mysql = append(mysql, part...)
|
||||
if len(mysql) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
for i := range mysql {
|
||||
mysql[i].region = self
|
||||
ret = append(ret, &mysql[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIDBInstanceById(id string) (cloudprovider.ICloudDBInstance, error) {
|
||||
if strings.HasPrefix(id, "cdb-") {
|
||||
return self.GetMySQLInstanceById(id)
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateIDBInstance(opts *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) {
|
||||
switch opts.Engine {
|
||||
case api.DBINSTANCE_TYPE_MYSQL:
|
||||
rds, err := self.CreateMySQLDBInstance(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateMySQLDBInstance")
|
||||
}
|
||||
return rds, nil
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "For %s", opts.Engine)
|
||||
}
|
||||
@@ -41,6 +41,22 @@ clb.tencentcloudapi.com
|
||||
clb.ap-shanghai-fsi.tencentcloudapi.com
|
||||
clb.ap-shenzhen-fsi.tencentcloudapi.com
|
||||
|
||||
cdb.tencentcloudapi.com
|
||||
cdb.ap-shanghai-fsi.tencentcloudapi.com
|
||||
cdb.ap-shenzhen-fsi.tencentcloudapi.com
|
||||
|
||||
mariadb.tencentcloudapi.com
|
||||
mariadb.ap-shanghai-fsi.tencentcloudapi.com
|
||||
mariadb.ap-shenzhen-fsi.tencentcloudapi.com
|
||||
|
||||
postgres.tencentcloudapi.com
|
||||
postgres.ap-shanghai-fsi.tencentcloudapi.com
|
||||
postgres.ap-shenzhen-fsi.tencentcloudapi.com
|
||||
|
||||
sqlserver.tencentcloudapi.com
|
||||
sqlserver.ap-shanghai-fsi.tencentcloudapi.com
|
||||
sqlserver.ap-shenzhen-fsi.tencentcloudapi.com
|
||||
|
||||
lb.api.qcloud.com
|
||||
wss.api.qcloud.com
|
||||
cns.api.qcloud.com
|
||||
|
||||
@@ -46,11 +46,15 @@ const (
|
||||
|
||||
QCLOUD_DEFAULT_REGION = "ap-beijing"
|
||||
|
||||
QCLOUD_API_VERSION = "2017-03-12"
|
||||
QCLOUD_CLB_API_VERSION = "2018-03-17"
|
||||
QCLOUD_BILLING_API_VERSION = "2018-07-09"
|
||||
QCLOUD_AUDIT_API_VERSION = "2019-03-19"
|
||||
QCLOUD_CAM_API_VERSION = "2019-01-16"
|
||||
QCLOUD_API_VERSION = "2017-03-12"
|
||||
QCLOUD_CLB_API_VERSION = "2018-03-17"
|
||||
QCLOUD_BILLING_API_VERSION = "2018-07-09"
|
||||
QCLOUD_AUDIT_API_VERSION = "2019-03-19"
|
||||
QCLOUD_CAM_API_VERSION = "2019-01-16"
|
||||
QCLOUD_CDB_API_VERSION = "2017-03-20"
|
||||
QCLOUD_MARIADB_API_VERSION = "2017-03-12"
|
||||
QCLOUD_POSTGRES_API_VERSION = "2017-03-12"
|
||||
QCLOUD_SQLSERVER_API_VERSION = "2018-03-28"
|
||||
)
|
||||
|
||||
type QcloudClientConfig struct {
|
||||
@@ -167,6 +171,30 @@ func lbRequest(client *common.Client, apiName string, params map[string]string,
|
||||
return _phpJsonRequest(client, &lbJsonResponse{}, domain, "/v2/index.php", "", apiName, params, debug)
|
||||
}
|
||||
|
||||
// cdb
|
||||
func cdbRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
|
||||
domain := apiDomain("cdb", params)
|
||||
return _jsonRequest(client, domain, QCLOUD_CDB_API_VERSION, apiName, params, debug, true)
|
||||
}
|
||||
|
||||
// mariadb
|
||||
func mariadbRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
|
||||
domain := apiDomain("mariadb", params)
|
||||
return _jsonRequest(client, domain, QCLOUD_MARIADB_API_VERSION, apiName, params, debug, true)
|
||||
}
|
||||
|
||||
// postgres
|
||||
func postgresRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
|
||||
domain := apiDomain("postgres", params)
|
||||
return _jsonRequest(client, domain, QCLOUD_POSTGRES_API_VERSION, apiName, params, debug, true)
|
||||
}
|
||||
|
||||
// sqlserver
|
||||
func sqlserverRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
|
||||
domain := apiDomain("sqlserver", params)
|
||||
return _jsonRequest(client, domain, QCLOUD_SQLSERVER_API_VERSION, apiName, params, debug, true)
|
||||
}
|
||||
|
||||
// ssl 证书服务
|
||||
func wssRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) {
|
||||
domain := "wss.api.qcloud.com"
|
||||
@@ -514,6 +542,38 @@ func (client *SQcloudClient) lbRequest(apiName string, params map[string]string)
|
||||
return lbRequest(cli, apiName, params, client.debug)
|
||||
}
|
||||
|
||||
func (client *SQcloudClient) cdbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
cli, err := client.getDefaultClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cdbRequest(cli, apiName, params, client.debug)
|
||||
}
|
||||
|
||||
func (client *SQcloudClient) mariadbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
cli, err := client.getDefaultClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mariadbRequest(cli, apiName, params, client.debug)
|
||||
}
|
||||
|
||||
func (client *SQcloudClient) postgresRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
cli, err := client.getDefaultClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return postgresRequest(cli, apiName, params, client.debug)
|
||||
}
|
||||
|
||||
func (client *SQcloudClient) sqlserverRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
cli, err := client.getDefaultClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sqlserverRequest(cli, apiName, params, client.debug)
|
||||
}
|
||||
|
||||
func (client *SQcloudClient) wssRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
cli, err := client.getDefaultClient()
|
||||
if err != nil {
|
||||
@@ -830,7 +890,7 @@ func (self *SQcloudClient) GetCapabilities() []string {
|
||||
cloudprovider.CLOUD_CAPABILITY_NETWORK,
|
||||
cloudprovider.CLOUD_CAPABILITY_LOADBALANCER,
|
||||
cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE,
|
||||
// cloudprovider.CLOUD_CAPABILITY_RDS,
|
||||
cloudprovider.CLOUD_CAPABILITY_RDS,
|
||||
// cloudprovider.CLOUD_CAPABILITY_CACHE,
|
||||
cloudprovider.CLOUD_CAPABILITY_EVENT,
|
||||
cloudprovider.CLOUD_CAPABILITY_CLOUDID,
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
var (
|
||||
SUPPORTED_ENGINE_VERSION = []string{"5.7", "10.0", "10.1"}
|
||||
)
|
||||
|
||||
type SaleZoneInfo struct {
|
||||
Zone string
|
||||
ZoneId string
|
||||
ZoneName string
|
||||
}
|
||||
|
||||
type SAvailableChoice struct {
|
||||
MasterZone SaleZoneInfo
|
||||
SlaveZones []SaleZoneInfo
|
||||
}
|
||||
|
||||
type SRegionSaleInfo struct {
|
||||
AvailableChoice []SAvailableChoice
|
||||
Region string
|
||||
RegionId string
|
||||
RegionName string
|
||||
ZoneList []SaleZoneInfo
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeSaleInfo() ([]SRegionSaleInfo, error) {
|
||||
resp, err := self.mariadbRequest("DescribeSaleInfo", map[string]string{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeSaleInfo")
|
||||
}
|
||||
saleInfo := []SRegionSaleInfo{}
|
||||
err = resp.Unmarshal(&saleInfo, "RegionList")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return saleInfo, nil
|
||||
}
|
||||
|
||||
type SInstanceSpec struct {
|
||||
Cpu int
|
||||
Machine string
|
||||
MaxStorage int
|
||||
Memory int
|
||||
MinStorage int
|
||||
NodeCount int
|
||||
Pid int
|
||||
Qps int
|
||||
SuitInfo string
|
||||
}
|
||||
|
||||
type SInstanceSpecs struct {
|
||||
Machine string
|
||||
SpecInfos []SInstanceSpec
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeDBInstanceSpecs() ([]SInstanceSpecs, error) {
|
||||
resp, err := self.mariadbRequest("DescribeDBInstanceSpecs", map[string]string{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeDBInstanceSpecs")
|
||||
}
|
||||
specs := []SInstanceSpecs{}
|
||||
err = resp.Unmarshal(&specs, "Specs")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return specs, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ListMariadbSkus() ([]SDBInstanceSku, error) {
|
||||
skus := []SDBInstanceSku{}
|
||||
|
||||
saleRegions, err := self.DescribeSaleInfo()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeSaleInfo")
|
||||
}
|
||||
|
||||
for _, saleRegion := range saleRegions {
|
||||
if saleRegion.Region == self.Region {
|
||||
specs, err := self.DescribeDBInstanceSpecs()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeDBInstanceSpecs")
|
||||
}
|
||||
for _, spec := range specs {
|
||||
for _, info := range spec.SpecInfos {
|
||||
sku := SDBInstanceSku{
|
||||
Region: self.Region,
|
||||
Engine: api.DBINSTANCE_TYPE_MARIADB,
|
||||
Cpu: info.Cpu,
|
||||
StorageMax: info.MaxStorage,
|
||||
StorageMin: info.MinStorage,
|
||||
StorageStep: 10,
|
||||
MemoryMb: info.Memory * 1024,
|
||||
Qps: info.Qps,
|
||||
Description: info.SuitInfo,
|
||||
Category: "标准版",
|
||||
Status: api.DBINSTANCE_SKU_AVAILABLE,
|
||||
}
|
||||
if info.NodeCount == 3 {
|
||||
sku.Category = "金融版"
|
||||
}
|
||||
for _, engineVersion := range SUPPORTED_ENGINE_VERSION {
|
||||
sku.EngineVersion = engineVersion
|
||||
sku.Zone2 = ""
|
||||
for _, zone := range saleRegion.AvailableChoice {
|
||||
sku.Zone1 = zone.MasterZone.Zone
|
||||
for _, slaveZone := range zone.SlaveZones {
|
||||
sku.Zone2 = slaveZone.Zone
|
||||
skus = append(skus, sku)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return skus, nil
|
||||
}
|
||||
@@ -0,0 +1,811 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
billingapi "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SlaveInstanceInfo struct {
|
||||
Region string
|
||||
Vip string
|
||||
VpcId int
|
||||
Vport int
|
||||
Zone string
|
||||
}
|
||||
|
||||
type SlaveInfo struct {
|
||||
First SlaveInstanceInfo
|
||||
Second SlaveInstanceInfo
|
||||
}
|
||||
|
||||
type SDrInfo struct {
|
||||
Status int
|
||||
Zone string
|
||||
InstanceId string
|
||||
Region string
|
||||
SyncStatus string
|
||||
InstanceName string
|
||||
InstanceType string
|
||||
}
|
||||
|
||||
type SMasterInfo struct {
|
||||
Region string
|
||||
RegionId int
|
||||
ZoneId int
|
||||
Zone string
|
||||
InstanceId string
|
||||
ResourceId string
|
||||
Status int
|
||||
InstanceName string
|
||||
InstanceType int
|
||||
TaskStatus int
|
||||
Memory int
|
||||
Volume int
|
||||
DeviceType string
|
||||
Qps int
|
||||
VpcId int
|
||||
SubnetId int
|
||||
ExClusterId string
|
||||
ExClusterName string
|
||||
}
|
||||
|
||||
type SRoGroup struct {
|
||||
RoGroupMode string
|
||||
RoGroupId string
|
||||
RoGroupName string
|
||||
RoOfflineDelay int
|
||||
RoMaxDelayTime int
|
||||
MinRoInGroup int
|
||||
WeightMode string
|
||||
Weight int
|
||||
// RoInstances
|
||||
Vip string
|
||||
Vport int
|
||||
UniqVpcId string
|
||||
UniqSubnetId string
|
||||
RoGroupRegion string
|
||||
RoGroupZone string
|
||||
}
|
||||
|
||||
type SRoVipInfo struct {
|
||||
RoVipStatus int
|
||||
RoSubnetId int
|
||||
RoVpcId int
|
||||
RoVport int
|
||||
RoVip string
|
||||
}
|
||||
|
||||
type SMySQLInstance struct {
|
||||
region *SRegion
|
||||
multicloud.SDBInstanceBase
|
||||
|
||||
AutoRenew int
|
||||
CdbError int
|
||||
Cpu int
|
||||
CreateTime time.Time
|
||||
DeadlineTime string
|
||||
DeployGroupId string
|
||||
DeployMode int
|
||||
DeviceClass string
|
||||
DeviceType string
|
||||
DrInfo []SDrInfo
|
||||
EngineVersion string
|
||||
ExClusterId string
|
||||
HourFeeStatus int
|
||||
InitFlag int
|
||||
InstanceId string
|
||||
InstanceName string
|
||||
InstanceType int
|
||||
IsolateTime string
|
||||
MasterInfo SMasterInfo
|
||||
Memory int
|
||||
OfflineTime string
|
||||
PayType int
|
||||
PhysicalId string
|
||||
ProjectId int
|
||||
ProtectMode string
|
||||
Qps int
|
||||
Region string
|
||||
RegionId string
|
||||
ResourceId string
|
||||
RoGroups []SRoGroup
|
||||
RoVipInfo SRoVipInfo
|
||||
SecurityGroupIds []string
|
||||
SlaveInfo SlaveInfo
|
||||
Status int
|
||||
SubnetId int
|
||||
//TagList": null,
|
||||
TaskStatus int
|
||||
UniqSubnetId string
|
||||
UniqVpcId string
|
||||
Vip string
|
||||
Volume int
|
||||
VpcId int
|
||||
Vport int
|
||||
WanDomain string
|
||||
WanPort int
|
||||
WanStatus int
|
||||
Zone string
|
||||
ZoneId int
|
||||
ZoneName string
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetId() string {
|
||||
return self.InstanceId
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetGlobalId() string {
|
||||
return self.InstanceId
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetName() string {
|
||||
if len(self.InstanceName) > 0 {
|
||||
return self.InstanceName
|
||||
}
|
||||
return self.InstanceId
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetDiskSizeGB() int {
|
||||
return self.Volume
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetEngine() string {
|
||||
return api.DBINSTANCE_TYPE_MYSQL
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetEngineVersion() string {
|
||||
return self.EngineVersion
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetIVpcId() string {
|
||||
return self.UniqVpcId
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) Refresh() error {
|
||||
rds, err := self.region.GetMySQLInstanceById(self.InstanceId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetMySQLInstanceById(%s)", self.InstanceId)
|
||||
}
|
||||
return jsonutils.Update(self, rds)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetInstanceType() string {
|
||||
return fmt.Sprintf("%d核%dMB", self.Cpu, self.Memory)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetMaintainTime() string {
|
||||
timeWindow, err := self.region.DescribeMySQLTimeWindow(self.InstanceId)
|
||||
if err != nil {
|
||||
log.Errorf("DescribeMySQLTimeWindow %s error: %v", self.InstanceId, err)
|
||||
return ""
|
||||
}
|
||||
return timeWindow.String()
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetDBNetwork() (*cloudprovider.SDBInstanceNetwork, error) {
|
||||
return &cloudprovider.SDBInstanceNetwork{NetworkId: self.UniqSubnetId, IP: self.Vip}, nil
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetConnectionStr() string {
|
||||
if self.WanStatus == 1 {
|
||||
return fmt.Sprintf("%s:%d", self.WanDomain, self.WanPort)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetInternalConnectionStr() string {
|
||||
return fmt.Sprintf("%s:%d", self.Vip, self.Vport)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) Reboot() error {
|
||||
return self.region.RebootMySQLInstance(self.InstanceId)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) ChangeConfig(ctx context.Context, opts *cloudprovider.SManagedDBInstanceChangeConfig) error {
|
||||
return self.region.UpgradeMySQLDBInstance(self.InstanceId, opts.VmemSizeMb, opts.DiskSizeGB)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetMasterInstanceId() string {
|
||||
return self.MasterInfo.InstanceId
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetSecurityGroupId() string {
|
||||
if len(self.SecurityGroupIds) > 0 {
|
||||
return self.SecurityGroupIds[0]
|
||||
}
|
||||
if self.DeviceType == "BASIC" {
|
||||
return ""
|
||||
}
|
||||
secgroups, err := self.region.DescribeMySQLDBSecurityGroups(self.InstanceId)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get instance %s security group info %v", self.InstanceId, err)
|
||||
return ""
|
||||
}
|
||||
if len(secgroups) > 0 {
|
||||
return secgroups[0].SecurityGroupId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) Renew(bc billing.SBillingCycle) error {
|
||||
month := bc.GetMonths()
|
||||
return self.region.RenewMySQLDBInstance(self.InstanceId, month)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) OpenPublicConnection() error {
|
||||
if self.WanStatus == 0 {
|
||||
return self.region.OpenMySQLWanService(self.InstanceId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) ClosePublicConnection() error {
|
||||
if self.WanStatus == 1 {
|
||||
return self.region.CloseMySQLWanService(self.InstanceId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetPort() int {
|
||||
return self.Vport
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetStatus() string {
|
||||
if self.InitFlag == 0 {
|
||||
return api.DBINSTANCE_INIT
|
||||
}
|
||||
switch self.TaskStatus {
|
||||
case 0:
|
||||
switch self.Status {
|
||||
case 0:
|
||||
return api.DBINSTANCE_DEPLOYING
|
||||
case 1:
|
||||
return api.DBINSTANCE_RUNNING
|
||||
case 4, 5:
|
||||
return api.DBINSTANCE_DELETING
|
||||
}
|
||||
case 1:
|
||||
case 2: //数据导入中
|
||||
return api.DBINSTANCE_IMPORTING
|
||||
case 3, 4: //开放关闭外网地址
|
||||
return api.DBINSTANCE_DEPLOYING
|
||||
case 10:
|
||||
return api.DBINSTANCE_REBOOTING
|
||||
case 12:
|
||||
return api.DBINSTANCE_MIGRATING
|
||||
default:
|
||||
return api.DBINSTANCE_DEPLOYING
|
||||
}
|
||||
return api.DBINSTANCE_UNKNOWN
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetCategory() string {
|
||||
return strings.ToLower(self.DeviceType)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetStorageType() string {
|
||||
switch self.DeviceType {
|
||||
case "BASIC":
|
||||
return api.QCLOUD_DBINSTANCE_STORAGE_TYPE_CLOUD_SSD
|
||||
default:
|
||||
return api.QCLOUD_DBINSTANCE_STORAGE_TYPE_LOCAL_SSD
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetCreatedAt() time.Time {
|
||||
// 2019-12-25 09:00:43 #非UTC时间
|
||||
return self.CreateTime.Add(time.Hour * -8)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetBillingType() string {
|
||||
if self.PayType == 0 {
|
||||
return billingapi.BILLING_TYPE_PREPAID
|
||||
}
|
||||
return billingapi.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) SetAutoRenew(autoRenew bool) error {
|
||||
return self.region.ModifyMySQLAutoRenewFlag([]string{self.InstanceId}, autoRenew)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) IsAutoRenew() bool {
|
||||
return self.AutoRenew == 1
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetExpiredAt() time.Time {
|
||||
t, _ := timeutils.ParseTimeStr(self.DeadlineTime)
|
||||
if t.IsZero() {
|
||||
return t
|
||||
}
|
||||
return t.Add(time.Hour * -8)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetVcpuCount() int {
|
||||
return self.Cpu
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetVmemSizeMB() int {
|
||||
return self.Memory
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetZone1Id() string {
|
||||
return self.Zone
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetZone2Id() string {
|
||||
return self.SlaveInfo.First.Zone
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetZone3Id() string {
|
||||
return self.SlaveInfo.Second.Zone
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetProjectId() string {
|
||||
return fmt.Sprintf("%d", self.ProjectId)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) Delete() error {
|
||||
err := self.region.IsolateMySQLDBInstance(self.InstanceId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "IsolateMySQLDBInstance")
|
||||
}
|
||||
return self.region.OfflineIsolatedMySQLInstances([]string{self.InstanceId})
|
||||
}
|
||||
|
||||
func (self *SRegion) ListMySQLInstances(ids []string, offset, limit int) ([]SMySQLInstance, int, error) {
|
||||
if limit < 1 || limit > 50 {
|
||||
limit = 50
|
||||
}
|
||||
params := map[string]string{
|
||||
"Offset": fmt.Sprintf("%d", offset),
|
||||
"Limit": fmt.Sprintf("%d", limit),
|
||||
}
|
||||
for idx, id := range ids {
|
||||
params[fmt.Sprintf("InstanceIds.%d", idx)] = id
|
||||
}
|
||||
resp, err := self.cdbRequest("DescribeDBInstances", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeDBInstances")
|
||||
}
|
||||
items := []SMySQLInstance{}
|
||||
err = resp.Unmarshal(&items, "Items")
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
total, _ := resp.Float("TotalCount")
|
||||
return items, int(total), nil
|
||||
}
|
||||
|
||||
type SAsyncRequestResult struct {
|
||||
Info string
|
||||
Status string
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeMySQLAsyncRequestInfo(id string) (*SAsyncRequestResult, error) {
|
||||
resp, err := self.cdbRequest("DescribeAsyncRequestInfo", map[string]string{"AsyncRequestId": id})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeAsyncRequestInfo")
|
||||
}
|
||||
result := SAsyncRequestResult{}
|
||||
err = resp.Unmarshal(&result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) waitAsyncAction(action string, resId, asyncRequestId string) error {
|
||||
if len(asyncRequestId) == 0 {
|
||||
return errors.Error("Missing AsyncRequestId")
|
||||
}
|
||||
return cloudprovider.Wait(time.Second*10, time.Minute*20, func() (bool, error) {
|
||||
result, err := self.DescribeMySQLAsyncRequestInfo(asyncRequestId)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, action)
|
||||
}
|
||||
log.Debugf("task %s(%s) for mysql instance %s status: %s", action, asyncRequestId, resId, result.Status)
|
||||
switch result.Status {
|
||||
case "FAILED", "KILLED", "REMOVED", "PAUSED":
|
||||
return true, errors.Errorf(result.Info)
|
||||
case "SUCCESS":
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (self *SRegion) RebootMySQLInstance(id string) error {
|
||||
resp, err := self.cdbRequest("RestartDBInstances", map[string]string{"InstanceIds.0": id})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "RestartDBInstances")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("RestartDBInstances", id, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeMySQLDBInstanceInfo(id string) (*SMySQLInstance, error) {
|
||||
resp, err := self.cdbRequest("DescribeDBInstanceInfo", map[string]string{"InstanceId": id})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeDBInstanceInfo")
|
||||
}
|
||||
result := SMySQLInstance{region: self}
|
||||
err = resp.Unmarshal(&result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) RenewMySQLDBInstance(id string, month int) error {
|
||||
params := map[string]string{
|
||||
"InstanceId": id,
|
||||
"TimeSpan": fmt.Sprintf("%d", month),
|
||||
}
|
||||
_, err := self.cdbRequest("RenewDBInstance", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "RenewDBInstance")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) OfflineIsolatedMySQLInstances(ids []string) error {
|
||||
params := map[string]string{}
|
||||
for idx, id := range ids {
|
||||
params[fmt.Sprintf("InstanceIds.%d", idx)] = id
|
||||
}
|
||||
_, err := self.cdbRequest("OfflineIsolatedInstances", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "OfflineIsolatedInstances")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ReleaseIsolatedMySQLDBInstances(ids []string) error {
|
||||
params := map[string]string{}
|
||||
for idx, id := range ids {
|
||||
params[fmt.Sprintf("InstanceIds.%d", idx)] = id
|
||||
}
|
||||
resp, err := self.cdbRequest("ReleaseIsolatedDBInstances", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ReleaseIsolatedDBInstances")
|
||||
}
|
||||
result := []struct {
|
||||
InstanceId string
|
||||
Code int
|
||||
Message string
|
||||
}{}
|
||||
err = resp.Unmarshal(&result, "Items")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
msg := []string{}
|
||||
for i := range result {
|
||||
if result[i].Code != 0 {
|
||||
msg = append(msg, fmt.Sprintf("instance %s release isolate error: %s", result[i].InstanceId, result[i].Message))
|
||||
}
|
||||
}
|
||||
if len(msg) > 0 {
|
||||
return errors.Error(strings.Join(msg, " "))
|
||||
}
|
||||
return cloudprovider.Wait(time.Second, time.Minute*10, func() (bool, error) {
|
||||
instances, _, err := self.ListMySQLInstances(ids, 0, len(ids))
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "ListMySQLInstances")
|
||||
}
|
||||
for i := range instances {
|
||||
if instances[i].Status == 4 || instances[i].Status == 5 {
|
||||
log.Debugf("mysql instance %s(%s) current be isolate", instances[i].InstanceName, instances[i].InstanceId)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (self *SRegion) IsolateMySQLDBInstance(id string) error {
|
||||
params := map[string]string{"InstanceId": id}
|
||||
resp, err := self.cdbRequest("IsolateDBInstance", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "IsolateDBInstance")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
if len(asyncRequestId) > 0 {
|
||||
return self.waitAsyncAction("IsolateDBInstance", id, asyncRequestId)
|
||||
}
|
||||
return cloudprovider.Wait(time.Second*10, time.Minute*5, func() (bool, error) {
|
||||
instances, _, err := self.ListMySQLInstances([]string{id}, 0, 1)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "ListMySQLInstances(%s)", id)
|
||||
}
|
||||
statusMap := map[int]string{0: "创建中", 1: "运行中", 4: "隔离中", 5: "已隔离"}
|
||||
for _, rds := range instances {
|
||||
status, _ := statusMap[rds.Status]
|
||||
log.Debugf("instance %s(%s) status %d(%s)", rds.InstanceName, rds.InstanceId, rds.Status, status)
|
||||
if rds.Status != 5 {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (self *SRegion) CloseMySQLWanService(id string) error {
|
||||
params := map[string]string{"InstanceId": id}
|
||||
resp, err := self.cdbRequest("CloseWanService", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "CloseWanService")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("CloseWanService", id, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SRegion) OpenMySQLWanService(id string) error {
|
||||
params := map[string]string{"InstanceId": id}
|
||||
resp, err := self.cdbRequest("OpenWanService", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "OpenWanService")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("OpenWanService", id, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SRegion) InitMySQLDBInstances(ids []string, password string, parameters map[string]string, vport int) error {
|
||||
params := map[string]string{"NewPassword": password}
|
||||
for idx, id := range ids {
|
||||
params[fmt.Sprintf("InstanceIds.%d", idx)] = id
|
||||
}
|
||||
i := 0
|
||||
for k, v := range parameters {
|
||||
params[fmt.Sprintf("Parameters.%d.name", i)] = k
|
||||
params[fmt.Sprintf("Parameters.%d.value", i)] = v
|
||||
i++
|
||||
}
|
||||
if vport >= 1024 && vport <= 65535 {
|
||||
params["Vport"] = fmt.Sprintf("%d", vport)
|
||||
}
|
||||
resp, err := self.cdbRequest("InitDBInstances", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "InitDBInstances")
|
||||
}
|
||||
asyncRequestIds := []string{}
|
||||
err = resp.Unmarshal(&asyncRequestIds, "AsyncRequestIds")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
for idx, requestId := range asyncRequestIds {
|
||||
err = self.waitAsyncAction("InitDBInstances", fmt.Sprintf("%d", idx), requestId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) UpgradeMySQLDBInstance(id string, memoryMb int, volumeGb int) error {
|
||||
params := map[string]string{
|
||||
"InstanceId": id,
|
||||
"Memory": fmt.Sprintf("%d", memoryMb),
|
||||
"Volume": fmt.Sprintf("%d", volumeGb),
|
||||
}
|
||||
resp, err := self.cdbRequest("UpgradeDBInstance", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "UpgradeDBInstance")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("UpgradeDBInstance", id, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SRegion) ModifyMySQLAutoRenewFlag(ids []string, autoRenew bool) error {
|
||||
params := map[string]string{}
|
||||
for idx, id := range ids {
|
||||
params[fmt.Sprintf("InstanceIds.%d", idx)] = id
|
||||
}
|
||||
params["AutoRenew"] = fmt.Sprintf("%d", autoRenew)
|
||||
_, err := self.cdbRequest("ModifyAutoRenewFlag", params)
|
||||
return err
|
||||
}
|
||||
|
||||
type SMaintenanceTime struct {
|
||||
Monday []string
|
||||
Tuesday []string
|
||||
Wednesday []string
|
||||
Thursday []string
|
||||
Friday []string
|
||||
Saturday []string
|
||||
Sunday []string
|
||||
}
|
||||
|
||||
func (w SMaintenanceTime) String() string {
|
||||
windows := []string{}
|
||||
for k, v := range map[string][]string{
|
||||
"Monday": w.Monday,
|
||||
"Tuesday": w.Tuesday,
|
||||
"Wednesday": w.Wednesday,
|
||||
"Thursday": w.Thursday,
|
||||
"Friday": w.Friday,
|
||||
"Saturday": w.Saturday,
|
||||
"Sunday": w.Sunday,
|
||||
} {
|
||||
if len(v) > 0 {
|
||||
windows = append(windows, fmt.Sprintf("%s: %s", k, strings.Join(v, " ")))
|
||||
}
|
||||
}
|
||||
return strings.Join(windows, "\n")
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeMySQLTimeWindow(id string) (*SMaintenanceTime, error) {
|
||||
params := map[string]string{"InstanceId": id}
|
||||
resp, err := self.cdbRequest("DescribeTimeWindow", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeTimeWindow")
|
||||
}
|
||||
timeWindow := &SMaintenanceTime{}
|
||||
err = resp.Unmarshal(timeWindow)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return timeWindow, nil
|
||||
}
|
||||
|
||||
type SDBSecgroup struct {
|
||||
ProjectId int
|
||||
CreateTime time.Time
|
||||
SecurityGroupId string
|
||||
SecurityGroupName string
|
||||
SecurityGroupRemark string
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeMySQLDBSecurityGroups(instanceId string) ([]SDBSecgroup, error) {
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
}
|
||||
resp, err := self.cdbRequest("DescribeDBSecurityGroups", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeDBSecurityGroups")
|
||||
}
|
||||
result := []SDBSecgroup{}
|
||||
err = resp.Unmarshal(&result, "Groups")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateMySQLDBInstance(opts *cloudprovider.SManagedDBInstanceCreateConfig) (*SMySQLInstance, error) {
|
||||
params := map[string]string{
|
||||
"InstanceName": opts.Name,
|
||||
"GoodsNum": "1",
|
||||
"Memory": fmt.Sprintf("%d", opts.VmemSizeMb),
|
||||
"Volume": fmt.Sprintf("%d", opts.DiskSizeGB),
|
||||
"EngineVersion": opts.EngineVersion,
|
||||
}
|
||||
if len(opts.VpcId) > 0 {
|
||||
params["UniqVpcId"] = opts.VpcId
|
||||
}
|
||||
if len(opts.NetworkId) > 0 {
|
||||
params["UniqSubnetId"] = opts.NetworkId
|
||||
}
|
||||
if len(opts.ProjectId) > 0 {
|
||||
params["ProjectId"] = opts.ProjectId
|
||||
}
|
||||
if opts.Port > 1024 && opts.Port < 65535 {
|
||||
params["Port"] = fmt.Sprintf("%d", opts.Port)
|
||||
}
|
||||
if len(opts.Password) > 0 {
|
||||
params["Password"] = opts.Password
|
||||
}
|
||||
if len(opts.SecgroupId) > 0 {
|
||||
params["SecurityGroup.0"] = opts.SecgroupId
|
||||
}
|
||||
action := "CreateDBInstanceHour"
|
||||
if opts.BillingCycle != nil {
|
||||
params["Period"] = fmt.Sprintf("%d", opts.BillingCycle.GetMonths())
|
||||
action = "CreateDBInstance"
|
||||
}
|
||||
switch opts.Category {
|
||||
case api.QCLOUD_DBINSTANCE_CATEGORY_HA, api.QCLOUD_DBINSTANCE_CATEGORY_BASIC:
|
||||
params["DeviceType"] = strings.ToUpper(opts.Category)
|
||||
case api.QCLOUD_DBINSTANCE_CATEGORY_FINANCE:
|
||||
params["DeviceType"] = "HA"
|
||||
params["ProtectMode"] = "2"
|
||||
}
|
||||
if len(opts.Zone1) > 0 {
|
||||
params["Zone"] = opts.Zone1
|
||||
}
|
||||
if len(opts.Zone2) > 0 {
|
||||
params["SlaveZone"] = opts.Zone2
|
||||
}
|
||||
if len(opts.Zone3) > 0 {
|
||||
params["BackupZone"] = opts.Zone3
|
||||
}
|
||||
params["ClientToken"] = utils.GenRequestId(20)
|
||||
resp, err := self.cdbRequest(action, params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cdbRequest")
|
||||
}
|
||||
instanceIds := []string{}
|
||||
err = resp.Unmarshal(&instanceIds, "InstanceIds")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
if len(instanceIds) == 0 {
|
||||
return nil, fmt.Errorf("%s not return InstanceIds", action)
|
||||
}
|
||||
err = cloudprovider.Wait(time.Second*10, time.Minute*20, func() (bool, error) {
|
||||
instances, _, err := self.ListMySQLInstances(instanceIds, 0, 1)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "ListMySQLInstances(%s)", instanceIds)
|
||||
}
|
||||
for _, rds := range instances {
|
||||
log.Debugf("instance %s(%s) task status: %d", rds.InstanceName, rds.InstanceId, rds.TaskStatus)
|
||||
if rds.TaskStatus == 1 {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cloudprovider.Wait After create")
|
||||
}
|
||||
return self.GetMySQLInstanceById(instanceIds[0])
|
||||
}
|
||||
|
||||
func (self *SRegion) GetMySQLInstanceById(id string) (*SMySQLInstance, error) {
|
||||
part, total, err := self.ListMySQLInstances([]string{id}, 0, 20)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListMySQLInstances")
|
||||
}
|
||||
if total > 1 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "id: [%s]", id)
|
||||
}
|
||||
if total < 1 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
part[0].region = self
|
||||
return &part[0], nil
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) CreateDatabase(opts *cloudprovider.SDBInstanceDatabaseCreateConfig) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) CreateAccount(opts *cloudprovider.SDBInstanceAccountCreateConfig) error {
|
||||
return self.region.CreateMySQLAccount(self.InstanceId, opts)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) CreateIBackup(opts *cloudprovider.SDBInstanceBackupCreateConfig) (string, error) {
|
||||
tables := map[string]string{}
|
||||
for _, d := range opts.Databases {
|
||||
tables[d] = ""
|
||||
}
|
||||
return self.region.CreateMySQLBackup(self.InstanceId, tables)
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/fatih/set.v0"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SMySQLInstanceAccount struct {
|
||||
multicloud.SDBInstanceAccountBase
|
||||
rds *SMySQLInstance
|
||||
|
||||
Notes string
|
||||
Host string
|
||||
User string
|
||||
ModifyTime string
|
||||
ModifyPasswordTime string
|
||||
CreateTime string
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceAccount) GetName() string {
|
||||
return self.User
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceAccount) GetHost() string {
|
||||
return self.Host
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceAccount) ResetPassword(password string) error {
|
||||
return self.rds.region.ModifyMySQLAccountPassword(self.rds.InstanceId, password, map[string]string{self.User: self.Host})
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceAccount) Delete() error {
|
||||
return self.rds.region.DeleteMySQLAccounts(self.rds.InstanceId, map[string]string{self.User: self.Host})
|
||||
}
|
||||
|
||||
type sPrivilege struct {
|
||||
Database string
|
||||
Privilege string
|
||||
User string
|
||||
Host string
|
||||
}
|
||||
|
||||
func (p sPrivilege) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s-%s-%s", p.User, p.Host, p.Database, p.Privilege)
|
||||
}
|
||||
|
||||
func (p sPrivilege) GetDBName() string {
|
||||
return p.Database
|
||||
}
|
||||
|
||||
func (p sPrivilege) GetPrivilege() string {
|
||||
return p.Privilege
|
||||
}
|
||||
|
||||
func (self *SRegion) GrantAccountPrivilege(instanceId, user, host, database, privilege string) error {
|
||||
privileges := []string{}
|
||||
switch privilege {
|
||||
case api.DATABASE_PRIVILEGE_RW:
|
||||
privileges = api.QCLOUD_RW_PRIVILEGE_SET
|
||||
case api.DATABASE_PRIVILEGE_R:
|
||||
privileges = api.QCLOUD_R_PRIVILEGE_SET
|
||||
default:
|
||||
return fmt.Errorf("unknow privilege %s", privilege)
|
||||
}
|
||||
priv, err := self.DescribeAccountPrivileges(instanceId, user, host)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DescribeAccountPrivileges")
|
||||
}
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"Accounts.0.User": user,
|
||||
"Accounts.0.Host": host,
|
||||
}
|
||||
for i, p := range priv.GlobalPrivileges {
|
||||
params[fmt.Sprintf("GlobalPrivileges.%d", i)] = p
|
||||
}
|
||||
find := false
|
||||
for i, p := range priv.DatabasePrivileges {
|
||||
params[fmt.Sprintf("DatabasePrivileges.%d.Database", i)] = p.Database
|
||||
if database == p.Database {
|
||||
p.Privileges = privileges
|
||||
find = true
|
||||
}
|
||||
for j, v := range p.Privileges {
|
||||
params[fmt.Sprintf("DatabasePrivileges.%d.Privileges.%d", i, j)] = v
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
params[fmt.Sprintf("DatabasePrivileges.%d.Database", len(priv.DatabasePrivileges))] = database
|
||||
for j, v := range privileges {
|
||||
params[fmt.Sprintf("DatabasePrivileges.%d.Privileges.%d", len(priv.DatabasePrivileges), j)] = v
|
||||
}
|
||||
}
|
||||
for i, p := range priv.TablePrivileges {
|
||||
params[fmt.Sprintf("TablePrivileges.%d.Database", i)] = p.Database
|
||||
params[fmt.Sprintf("TablePrivileges.%d.Table", i)] = p.Table
|
||||
for j, v := range p.Privileges {
|
||||
params[fmt.Sprintf("TablePrivileges.%d.Privileges.%d", i, j)] = v
|
||||
}
|
||||
}
|
||||
for i, p := range priv.ColumnPrivileges {
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Database", i)] = p.Database
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Table", i)] = p.Table
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Column", i)] = p.Column
|
||||
for j, v := range p.Privileges {
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Privileges.%d", i, j)] = v
|
||||
}
|
||||
}
|
||||
resp, err := self.cdbRequest("ModifyAccountPrivileges", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ModifyAccountPrivileges")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("ModifyAccountPrivileges", instanceId, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SRegion) RevokeAccountPrivilege(instanceId, user, host, database string) error {
|
||||
priv, err := self.DescribeAccountPrivileges(instanceId, user, host)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DescribeAccountPrivileges")
|
||||
}
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"Accounts.0.User": user,
|
||||
"Accounts.0.Host": host,
|
||||
}
|
||||
for i, p := range priv.GlobalPrivileges {
|
||||
params[fmt.Sprintf("GlobalPrivileges.%d", i)] = p
|
||||
}
|
||||
idx := 0
|
||||
for _, p := range priv.DatabasePrivileges {
|
||||
if p.Database == database {
|
||||
continue
|
||||
}
|
||||
params[fmt.Sprintf("DatabasePrivileges.%d.Database", idx)] = p.Database
|
||||
for i, v := range p.Privileges {
|
||||
params[fmt.Sprintf("DatabasePrivileges.%d.Privileges.%d", idx, i)] = v
|
||||
}
|
||||
}
|
||||
for i, p := range priv.TablePrivileges {
|
||||
params[fmt.Sprintf("TablePrivileges.%d.Database", i)] = p.Database
|
||||
params[fmt.Sprintf("TablePrivileges.%d.Table", i)] = p.Table
|
||||
for j, v := range p.Privileges {
|
||||
params[fmt.Sprintf("TablePrivileges.%d.Privileges.%d", i, j)] = v
|
||||
}
|
||||
}
|
||||
for i, p := range priv.ColumnPrivileges {
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Database", i)] = p.Database
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Table", i)] = p.Table
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Column", i)] = p.Column
|
||||
for j, v := range p.Privileges {
|
||||
params[fmt.Sprintf("ColumnPrivileges.%d.Privileges.%d", i, j)] = v
|
||||
}
|
||||
}
|
||||
resp, err := self.cdbRequest("ModifyAccountPrivileges", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ModifyAccountPrivileges")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("ModifyAccountPrivileges", instanceId, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceAccount) GrantPrivilege(database, privilege string) error {
|
||||
return self.rds.region.GrantAccountPrivilege(self.rds.InstanceId, self.User, self.Host, database, privilege)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceAccount) RevokePrivilege(database string) error {
|
||||
return self.rds.region.RevokeAccountPrivilege(self.rds.InstanceId, self.User, self.Host, database)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceAccount) GetIDBInstanceAccountPrivileges() ([]cloudprovider.ICloudDBInstanceAccountPrivilege, error) {
|
||||
if utils.IsInStringArray(self.User, []string{"mysql.infoschema", "mysql.session", "mysql.sys"}) {
|
||||
return []cloudprovider.ICloudDBInstanceAccountPrivilege{}, nil
|
||||
}
|
||||
priv, err := self.rds.region.DescribeAccountPrivileges(self.rds.InstanceId, self.User, self.Host)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeAccountPrivileges")
|
||||
}
|
||||
ret := []cloudprovider.ICloudDBInstanceAccountPrivilege{}
|
||||
rwSet := set.New(set.ThreadSafe)
|
||||
for _, p := range api.QCLOUD_RW_PRIVILEGE_SET {
|
||||
rwSet.Add(p)
|
||||
}
|
||||
rSet := set.New(set.ThreadSafe)
|
||||
for _, p := range api.QCLOUD_R_PRIVILEGE_SET {
|
||||
rSet.Add(p)
|
||||
}
|
||||
for _, p := range priv.DatabasePrivileges {
|
||||
pSet := set.New(set.ThreadSafe)
|
||||
for _, v := range p.Privileges {
|
||||
pSet.Add(v)
|
||||
}
|
||||
priv := strings.Join(p.Privileges, ",")
|
||||
if pSet.IsEqual(rSet) {
|
||||
priv = api.DATABASE_PRIVILEGE_R
|
||||
} else if pSet.IsEqual(rwSet) {
|
||||
priv = api.DATABASE_PRIVILEGE_RW
|
||||
}
|
||||
privilege := &sPrivilege{
|
||||
Database: p.Database,
|
||||
User: self.User,
|
||||
Host: self.Host,
|
||||
Privilege: priv,
|
||||
}
|
||||
ret = append(ret, privilege)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ModifyMySQLAccountPassword(instanceId string, password string, users map[string]string) error {
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"NewPassword": password,
|
||||
}
|
||||
idx := 0
|
||||
for user, host := range users {
|
||||
params[fmt.Sprintf("Accounts.%d.user", idx)] = user
|
||||
params[fmt.Sprintf("Accounts.%d.host", idx)] = host
|
||||
idx++
|
||||
}
|
||||
resp, err := self.cdbRequest("ModifyAccountPassword", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ModifyAccountPassword")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("ModifyAccountPassword", instanceId, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteMySQLAccounts(instanceId string, users map[string]string) error {
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
}
|
||||
idx := 0
|
||||
for user, host := range users {
|
||||
params[fmt.Sprintf("Accounts.%d.user", idx)] = user
|
||||
params[fmt.Sprintf("Accounts.%d.host", idx)] = host
|
||||
idx++
|
||||
}
|
||||
resp, err := self.cdbRequest("DeleteAccounts", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DeleteAccounts")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("DeleteAccounts", instanceId, asyncRequestId)
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeMySQLAccounts(instanceId string, offset, limit int) ([]SMySQLInstanceAccount, int, error) {
|
||||
if limit < 1 || limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"Offset": fmt.Sprintf("%d", offset),
|
||||
"Limit": fmt.Sprintf("%d", limit),
|
||||
}
|
||||
resp, err := self.cdbRequest("DescribeAccounts", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeAccounts")
|
||||
}
|
||||
ret := []SMySQLInstanceAccount{}
|
||||
err = resp.Unmarshal(&ret, "Items")
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
totalCount, _ := resp.Float("TotalCount")
|
||||
return ret, int(totalCount), nil
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetIDBInstanceAccounts() ([]cloudprovider.ICloudDBInstanceAccount, error) {
|
||||
ret := []cloudprovider.ICloudDBInstanceAccount{}
|
||||
for {
|
||||
part, total, err := self.region.DescribeMySQLAccounts(self.InstanceId, len(ret), 100)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeMySQLAccounts")
|
||||
}
|
||||
for i := range part {
|
||||
part[i].rds = self
|
||||
ret = append(ret, &part[i])
|
||||
}
|
||||
if len(ret) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateMySQLAccount(instanceId string, opts *cloudprovider.SDBInstanceAccountCreateConfig) error {
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"Password": opts.Password,
|
||||
"Accounts.0.User": opts.Name,
|
||||
"Accounts.0.Host": opts.Host,
|
||||
"Description": opts.Description,
|
||||
}
|
||||
resp, err := self.cdbRequest("CreateAccounts", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "CreateAccounts")
|
||||
}
|
||||
asyncRequestId, _ := resp.GetString("AsyncRequestId")
|
||||
return self.waitAsyncAction("CreateAccounts", instanceId, asyncRequestId)
|
||||
}
|
||||
|
||||
type SDatabasePrivilege struct {
|
||||
Privileges []string
|
||||
Database string
|
||||
}
|
||||
|
||||
type STablePrivilege struct {
|
||||
Database string
|
||||
Table string
|
||||
Privileges []string
|
||||
}
|
||||
|
||||
type SColumnPrivilege struct {
|
||||
Database string
|
||||
Table string
|
||||
Column string
|
||||
Privileges []string
|
||||
}
|
||||
|
||||
type SAccountPrivilege struct {
|
||||
GlobalPrivileges []string
|
||||
DatabasePrivileges []SDatabasePrivilege
|
||||
TablePrivileges []STablePrivilege
|
||||
ColumnPrivileges []SColumnPrivilege
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeAccountPrivileges(instanceId string, user, host string) (*SAccountPrivilege, error) {
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"User": user,
|
||||
"Host": host,
|
||||
}
|
||||
resp, err := self.cdbRequest("DescribeAccountPrivileges", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeAccountPrivileges")
|
||||
}
|
||||
priv := &SAccountPrivilege{}
|
||||
err = resp.Unmarshal(priv)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return priv, nil
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SMySQLInstanceBackup struct {
|
||||
multicloud.SDBInstanceBackupBase
|
||||
rds *SMySQLInstance
|
||||
|
||||
Name string
|
||||
Size int
|
||||
Date string
|
||||
IntranetUrl string
|
||||
InternetUrl string
|
||||
Type string
|
||||
BackupId int
|
||||
Status string
|
||||
FinishTime string
|
||||
Creator string
|
||||
StartTime string
|
||||
Method string
|
||||
Way string
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetId() string {
|
||||
return fmt.Sprintf("%d", self.BackupId)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetName() string {
|
||||
if len(self.Name) > 0 {
|
||||
return self.Name
|
||||
}
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetEngine() string {
|
||||
return api.DBINSTANCE_TYPE_MYSQL
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetStatus() string {
|
||||
switch self.Status {
|
||||
case "SUCCESS":
|
||||
return api.DBINSTANCE_BACKUP_READY
|
||||
case "FAILED":
|
||||
return api.DBINSTANCE_BACKUP_CREATE_FAILED
|
||||
case "RUNNING":
|
||||
return api.DBINSTANCE_BACKUP_CREATING
|
||||
default:
|
||||
return api.DBINSTANCE_BACKUP_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetEngineVersion() string {
|
||||
return self.rds.EngineVersion
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetDBInstanceId() string {
|
||||
return self.rds.InstanceId
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetStartTime() time.Time {
|
||||
start, err := timeutils.ParseTimeStr(self.StartTime)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return start.Add(time.Hour * -8)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetEndTime() time.Time {
|
||||
end, err := timeutils.ParseTimeStr(self.FinishTime)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return end.Add(time.Hour * -8)
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetBackupSizeMb() int {
|
||||
return self.Size / 1024 / 1024
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetDBNames() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) GetBackupMode() string {
|
||||
if self.Way == "manual" {
|
||||
return api.BACKUP_MODE_MANUAL
|
||||
}
|
||||
return api.BACKUP_MODE_AUTOMATED
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceBackup) Delete() error {
|
||||
return self.rds.region.DeleteBackup(self.rds.InstanceId, fmt.Sprintf("%d", self.BackupId))
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetIDBInstanceBackups() ([]cloudprovider.ICloudDBInstanceBackup, error) {
|
||||
backups := []cloudprovider.ICloudDBInstanceBackup{}
|
||||
for {
|
||||
part, total, err := self.region.DescribeMySQLBackups(self.InstanceId, len(backups), 100)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeMySQLBackups")
|
||||
}
|
||||
for i := range part {
|
||||
part[i].rds = self
|
||||
backups = append(backups, &part[i])
|
||||
}
|
||||
if len(backups) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return backups, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeMySQLBackups(instanceId string, offset, limit int) ([]SMySQLInstanceBackup, int, error) {
|
||||
if limit < 1 || limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
params := map[string]string{
|
||||
"Offset": fmt.Sprintf("%d", offset),
|
||||
"Limit": fmt.Sprintf("%d", limit),
|
||||
}
|
||||
if len(instanceId) > 0 {
|
||||
params["InstanceId"] = instanceId
|
||||
}
|
||||
resp, err := self.cdbRequest("DescribeBackups", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeBackups")
|
||||
}
|
||||
backups := []SMySQLInstanceBackup{}
|
||||
err = resp.Unmarshal(&backups, "Items")
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
totalCount, _ := resp.Float("TotalCount")
|
||||
return backups, int(totalCount), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteBackup(instanceId, id string) error {
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"BackupId": id,
|
||||
}
|
||||
_, err := self.cdbRequest("DeleteBackup", params)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DeleteBackup")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetMySQLInstanceBackup(instanceId, backupId string) (*SMySQLInstanceBackup, error) {
|
||||
backups := []SMySQLInstanceBackup{}
|
||||
for {
|
||||
part, total, err := self.DescribeMySQLBackups(instanceId, len(backups), 100)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeMySQLBackups")
|
||||
}
|
||||
for i := range part {
|
||||
if fmt.Sprintf("%d", part[i].BackupId) == backupId {
|
||||
return &part[i], nil
|
||||
}
|
||||
}
|
||||
backups = append(backups, part...)
|
||||
if len(backups) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("failed to found rds %s backup %s", instanceId, backupId)
|
||||
}
|
||||
|
||||
func (self *SRegion) waitMySQLBackupReady(instanceId, backupId string) error {
|
||||
return cloudprovider.Wait(time.Second*20, time.Minute*30, func() (bool, error) {
|
||||
backup, err := self.GetMySQLInstanceBackup(instanceId, backupId)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "GetMySQLInstanceBackup")
|
||||
}
|
||||
log.Infof("backup %s for instance %s status %s", backup.GetName(), instanceId, backup.Status)
|
||||
if utils.IsInStringArray(backup.Status, []string{"FAILED", "SUCCESS"}) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateMySQLBackup(instanceId string, tables map[string]string) (string, error) {
|
||||
params := map[string]string{
|
||||
"InstanceId": instanceId,
|
||||
"BackupMethod": "physical",
|
||||
}
|
||||
if len(tables) > 0 {
|
||||
params["BackupMethod"] = "logical"
|
||||
idx := 0
|
||||
for db, table := range tables {
|
||||
params[fmt.Sprintf("BackupDBTableList.%d.Db", idx)] = db
|
||||
if len(table) > 0 {
|
||||
params[fmt.Sprintf("BackupDBTableList.%d.Table", idx)] = table
|
||||
}
|
||||
idx++
|
||||
}
|
||||
}
|
||||
resp, err := self.cdbRequest("CreateBackup", params)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "CreateBackup")
|
||||
}
|
||||
_backupId, _ := resp.Float("BackupId")
|
||||
backupId := fmt.Sprintf("%d", int(_backupId))
|
||||
err = self.waitMySQLBackupReady(instanceId, backupId)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "waitBackupReady")
|
||||
}
|
||||
return backupId, nil
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SMySQLInstanceDatabase struct {
|
||||
rds *SMySQLInstance
|
||||
multicloud.SResourceBase
|
||||
|
||||
CharacterSet string
|
||||
DatabaseName string
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceDatabase) GetStatus() string {
|
||||
return api.DBINSTANCE_DATABASE_RUNNING
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceDatabase) GetId() string {
|
||||
return self.DatabaseName
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceDatabase) GetName() string {
|
||||
return self.DatabaseName
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceDatabase) GetGlobalId() string {
|
||||
return self.DatabaseName
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceDatabase) GetCharacterSet() string {
|
||||
return self.CharacterSet
|
||||
}
|
||||
|
||||
func (self *SMySQLInstanceDatabase) Delete() error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeMySQLDatabases(instanceId string, offset, limit int) ([]SMySQLInstanceDatabase, int, error) {
|
||||
if limit < 1 || limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
params := map[string]string{
|
||||
"Offset": fmt.Sprintf("%d", offset),
|
||||
"Limit": fmt.Sprintf("%d", limit),
|
||||
"InstanceId": instanceId,
|
||||
}
|
||||
resp, err := self.cdbRequest("DescribeDatabases", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeDatabases")
|
||||
}
|
||||
databases := []SMySQLInstanceDatabase{}
|
||||
err = resp.Unmarshal(&databases, "DatabaseList")
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
totalCount, _ := resp.Float("TotalCount")
|
||||
return databases, int(totalCount), nil
|
||||
}
|
||||
|
||||
func (rds *SMySQLInstance) GetIDBInstanceDatabases() ([]cloudprovider.ICloudDBInstanceDatabase, error) {
|
||||
ret := []cloudprovider.ICloudDBInstanceDatabase{}
|
||||
for {
|
||||
part, total, err := rds.region.DescribeMySQLDatabases(rds.InstanceId, len(ret), 100)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeMySQLDatabases")
|
||||
}
|
||||
for i := range part {
|
||||
part[i].rds = rds
|
||||
ret = append(ret, &part[i])
|
||||
}
|
||||
if len(ret) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type SellTypeConfig struct {
|
||||
Device string
|
||||
Type string
|
||||
CdbType string
|
||||
Memory int
|
||||
Cpu int
|
||||
VolumeMin int
|
||||
VolumeMax int
|
||||
VolumeStep int
|
||||
Connection int
|
||||
Qps int
|
||||
Iops int
|
||||
Info string
|
||||
Status string
|
||||
Tag string
|
||||
}
|
||||
|
||||
type SSellType struct {
|
||||
TypeName string
|
||||
EngineVersion []string
|
||||
Configs []SellTypeConfig
|
||||
}
|
||||
|
||||
type SZoneConf struct {
|
||||
DeployMode []int
|
||||
MasterZone []string
|
||||
SlaveZone []string
|
||||
BackupZone []string
|
||||
}
|
||||
|
||||
type SZoneSellConf struct {
|
||||
Status int
|
||||
ZoneName string
|
||||
IsCustom bool
|
||||
IsSupportDr bool
|
||||
IsSupportVpc bool
|
||||
HourInstanceSaleMaxNum int
|
||||
IsDefaultZone bool
|
||||
IsBm bool
|
||||
PayType []string
|
||||
ProtectMode string
|
||||
Zone string
|
||||
SellType []SSellType
|
||||
ZoneConf SZoneConf
|
||||
DrZone []string
|
||||
IsSupportRemoteRo bool
|
||||
}
|
||||
|
||||
type SRegionSellConf struct {
|
||||
RegionName string
|
||||
Area string
|
||||
IsDefaultRegion bool
|
||||
Region string
|
||||
ZonesConf []SZoneSellConf
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeDBZoneConfig() ([]SRegionSellConf, error) {
|
||||
resp, err := self.cdbRequest("DescribeDBZoneConfig", map[string]string{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeDBZoneConfig")
|
||||
}
|
||||
skus := []SRegionSellConf{}
|
||||
err = resp.Unmarshal(&skus, "Items")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return skus, nil
|
||||
}
|
||||
|
||||
type SDBInstanceSku struct {
|
||||
Region string
|
||||
Engine string
|
||||
EngineVersion string
|
||||
Category string
|
||||
Iops int
|
||||
Qps int
|
||||
MaxConnection int
|
||||
Cpu int
|
||||
MemoryMb int
|
||||
StorageType string
|
||||
StorageMin int
|
||||
StorageMax int
|
||||
StorageStep int
|
||||
Status string
|
||||
Description string
|
||||
Zone1 string
|
||||
Zone2 string
|
||||
Zone3 string
|
||||
}
|
||||
|
||||
func (self *SRegion) ListMysqlSkus() ([]SDBInstanceSku, error) {
|
||||
conf, err := self.DescribeDBZoneConfig()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeDBZoneConfig")
|
||||
}
|
||||
skus := []SDBInstanceSku{}
|
||||
for _, item := range conf {
|
||||
if item.Region != self.Region {
|
||||
continue
|
||||
}
|
||||
sku := SDBInstanceSku{
|
||||
Region: self.Region,
|
||||
Engine: api.DBINSTANCE_TYPE_MYSQL,
|
||||
Status: api.DBINSTANCE_SKU_SOLDOUT,
|
||||
}
|
||||
for _, zone := range item.ZonesConf {
|
||||
//0-未上线;1-上线;2-开放;3-停售;4-不展示
|
||||
if zone.Status == 0 || zone.Status == 4 {
|
||||
continue
|
||||
}
|
||||
if zone.Status == 1 || zone.Status == 2 {
|
||||
sku.Status = api.DBINSTANCE_SKU_AVAILABLE
|
||||
}
|
||||
if zone.IsBm { // 跳过黑石
|
||||
continue
|
||||
}
|
||||
for _, sellType := range zone.SellType {
|
||||
for _, sellConf := range sellType.Configs {
|
||||
sku.Cpu = sellConf.Cpu
|
||||
sku.MemoryMb = sellConf.Memory
|
||||
sku.Iops = sellConf.Iops
|
||||
sku.MaxConnection = sellConf.Connection
|
||||
sku.Qps = sellConf.Qps
|
||||
sku.StorageMin = sellConf.VolumeMin
|
||||
sku.StorageMax = sellConf.VolumeMax
|
||||
sku.StorageStep = sellConf.VolumeStep
|
||||
sku.Zone1 = zone.Zone
|
||||
for _, engineVersion := range sellType.EngineVersion {
|
||||
sku.EngineVersion = engineVersion
|
||||
sku.Category = sellConf.Type
|
||||
sku.Zone2, sku.Zone3 = "", ""
|
||||
sku.StorageType = api.STORAGE_LOCAL_SSD
|
||||
switch sellConf.Type {
|
||||
case "高可用版":
|
||||
for _, zone2 := range zone.ZoneConf.SlaveZone {
|
||||
sku.Zone2 = zone2
|
||||
skus = append(skus, sku)
|
||||
}
|
||||
if utils.IsInStringArray(engineVersion, []string{"5.6", "5.7", "8.0"}) {
|
||||
sku.Category = "金融版"
|
||||
for _, zone2 := range zone.ZoneConf.SlaveZone {
|
||||
sku.Zone2 = zone2
|
||||
sku.Zone3 = zone2
|
||||
skus = append(skus, sku)
|
||||
}
|
||||
}
|
||||
case "基础版":
|
||||
sku.StorageType = api.STORAGE_CLOUD_SSD
|
||||
skus = append(skus, sku)
|
||||
default:
|
||||
log.Errorf("unknow %s", sellConf.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return skus, nil
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type SpecItemInfoList struct {
|
||||
SpecCode string
|
||||
Version string
|
||||
VersionName string
|
||||
Cpu int
|
||||
Memory int
|
||||
MaxStorage int
|
||||
MinStorage int
|
||||
Qps int
|
||||
Pid int
|
||||
Type string
|
||||
}
|
||||
|
||||
type SpecInfoList struct {
|
||||
Region string
|
||||
Zone string
|
||||
SpecItemInfoList []SpecItemInfoList
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeProductConfig() ([]SpecInfoList, error) {
|
||||
resp, err := self.postgresRequest("DescribeProductConfig", map[string]string{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeProductConfig")
|
||||
}
|
||||
products := []SpecInfoList{}
|
||||
err = resp.Unmarshal(&products, "SpecInfoList")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return products, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ListPostgreSQLSkus() ([]SDBInstanceSku, error) {
|
||||
skus := []SDBInstanceSku{}
|
||||
products, err := self.DescribeProductConfig()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeProductConfig")
|
||||
}
|
||||
for _, product := range products {
|
||||
sku := SDBInstanceSku{
|
||||
Region: self.Region,
|
||||
Zone1: product.Zone,
|
||||
Engine: api.DBINSTANCE_TYPE_POSTGRESQL,
|
||||
Status: api.DBINSTANCE_SKU_AVAILABLE,
|
||||
Category: "双机高可用",
|
||||
}
|
||||
|
||||
for _, spec := range product.SpecItemInfoList {
|
||||
sku.EngineVersion = spec.Version
|
||||
sku.Qps = spec.Qps
|
||||
sku.Cpu = spec.Cpu
|
||||
sku.MemoryMb = spec.Memory * 1024
|
||||
sku.StorageMax = spec.MaxStorage
|
||||
sku.StorageMin = spec.MinStorage
|
||||
sku.StorageStep = 10
|
||||
|
||||
skus = append(skus, sku)
|
||||
}
|
||||
}
|
||||
return skus, nil
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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 qcloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type SqlServerSpecInfoList struct {
|
||||
Cpu int
|
||||
MachineType string
|
||||
MachineTypeName string
|
||||
MaxStorage int
|
||||
Memory int
|
||||
MinStorage int
|
||||
PayModeStatus string
|
||||
Pid int
|
||||
PostPid []int
|
||||
Qps int
|
||||
RoPid int
|
||||
SpecId int
|
||||
SuitInfo string
|
||||
Version string
|
||||
VersionName string
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeSqlServerProductConfig(zoneId string) ([]SqlServerSpecInfoList, error) {
|
||||
resp, err := self.sqlserverRequest("DescribeProductConfig", map[string]string{"Zone": zoneId})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeProductConfig")
|
||||
}
|
||||
specs := []SqlServerSpecInfoList{}
|
||||
err = resp.Unmarshal(&specs, "SpecInfoList")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return specs, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ListSQLServerSkus() ([]SDBInstanceSku, error) {
|
||||
zones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetIZones")
|
||||
}
|
||||
skus := []SDBInstanceSku{}
|
||||
for _, zone := range zones {
|
||||
products, err := self.DescribeSqlServerProductConfig(zone.GetId())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeSqlServerProductConfig")
|
||||
}
|
||||
for _, product := range products {
|
||||
sku := SDBInstanceSku{
|
||||
Region: self.Region,
|
||||
Zone1: zone.GetId(),
|
||||
Engine: api.DBINSTANCE_TYPE_SQLSERVER,
|
||||
EngineVersion: product.Version,
|
||||
}
|
||||
skus = append(skus, sku)
|
||||
}
|
||||
}
|
||||
return skus, nil
|
||||
}
|
||||
@@ -674,6 +674,26 @@ func (self *SRegion) lbRequest(apiName string, params map[string]string) (jsonut
|
||||
return self.client.lbRequest(apiName, params)
|
||||
}
|
||||
|
||||
func (self *SRegion) cdbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
params["Region"] = self.Region
|
||||
return self.client.cdbRequest(apiName, params)
|
||||
}
|
||||
|
||||
func (self *SRegion) mariadbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
params["Region"] = self.Region
|
||||
return self.client.mariadbRequest(apiName, params)
|
||||
}
|
||||
|
||||
func (self *SRegion) postgresRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
params["Region"] = self.Region
|
||||
return self.client.postgresRequest(apiName, params)
|
||||
}
|
||||
|
||||
func (self *SRegion) sqlserverRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
params["Region"] = self.Region
|
||||
return self.client.sqlserverRequest(apiName, params)
|
||||
}
|
||||
|
||||
func (self *SRegion) wssRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
return self.client.wssRequest(apiName, params)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// 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 shell
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type MariadbRegionListOptions struct {
|
||||
}
|
||||
shellutils.R(&MariadbRegionListOptions{}, "mariadb-region-list", "List mariadb region list", func(cli *qcloud.SRegion, args *MariadbRegionListOptions) error {
|
||||
regions, err := cli.DescribeSaleInfo()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DescribeSaleInfo")
|
||||
}
|
||||
printList(regions, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MariadbSpecListOptions struct {
|
||||
}
|
||||
|
||||
shellutils.R(&MariadbSpecListOptions{}, "mariadb-spec-list", "List mariadb specs", func(cli *qcloud.SRegion, args *MariadbSpecListOptions) error {
|
||||
specs, err := cli.DescribeDBInstanceSpecs()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DescribeDBInstanceSpecs")
|
||||
}
|
||||
printList(specs, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MariadbSkuListOptions struct {
|
||||
}
|
||||
|
||||
shellutils.R(&MariadbSkuListOptions{}, "mariadb-sku-list", "List mariadb skus", func(cli *qcloud.SRegion, args *MariadbSkuListOptions) error {
|
||||
skus, err := cli.ListMariadbSkus()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ListMariadbSkus")
|
||||
}
|
||||
printList(skus, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
// 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 shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type MysqlSkuListOptions struct {
|
||||
}
|
||||
shellutils.R(&MysqlSkuListOptions{}, "mysql-sku-list", "List mysql instance types", func(cli *qcloud.SRegion, args *MysqlSkuListOptions) error {
|
||||
skus, err := cli.ListMysqlSkus()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ListMysqlSkus")
|
||||
}
|
||||
printList(skus, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MysqlInstanceListOptions struct {
|
||||
Ids []string
|
||||
Offset int
|
||||
Limit int
|
||||
}
|
||||
|
||||
shellutils.R(&MysqlInstanceListOptions{}, "mysql-instance-list", "List mysql instance", func(cli *qcloud.SRegion, args *MysqlInstanceListOptions) error {
|
||||
result, _, err := cli.ListMySQLInstances(args.Ids, args.Offset, args.Limit)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ListMySQLInstances")
|
||||
}
|
||||
printList(result, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MySQLInstanceIdOptions struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
shellutils.R(&MySQLInstanceIdOptions{}, "mysql-instance-reboot", "Reboot mysql instance", func(cli *qcloud.SRegion, args *MySQLInstanceIdOptions) error {
|
||||
return cli.RebootMySQLInstance(args.ID)
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceIdOptions{}, "mysql-instance-isolate", "Isolate mysql instance", func(cli *qcloud.SRegion, args *MySQLInstanceIdOptions) error {
|
||||
return cli.IsolateMySQLDBInstance(args.ID)
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceIdOptions{}, "mysql-instance-offline-isolate", "Offline Isolate mysql instance", func(cli *qcloud.SRegion, args *MySQLInstanceIdOptions) error {
|
||||
return cli.OfflineIsolatedMySQLInstances([]string{args.ID})
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceIdOptions{}, "mysql-instance-release-isolate", "Release Isolate mysql instance", func(cli *qcloud.SRegion, args *MySQLInstanceIdOptions) error {
|
||||
return cli.ReleaseIsolatedMySQLDBInstances([]string{args.ID})
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceIdOptions{}, "mysql-instance-secgroup-list", "List mysql instance secgroups", func(cli *qcloud.SRegion, args *MySQLInstanceIdOptions) error {
|
||||
secgroups, err := cli.DescribeMySQLDBSecurityGroups(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(secgroups, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MySQLInstanceDBListOptions struct {
|
||||
MySQLInstanceIdOptions
|
||||
Offset int
|
||||
Limit int
|
||||
}
|
||||
|
||||
shellutils.R(&MySQLInstanceDBListOptions{}, "mysql-instance-database-list", "List mysql instance database", func(cli *qcloud.SRegion, args *MySQLInstanceDBListOptions) error {
|
||||
databases, totalCount, err := cli.DescribeMySQLDatabases(args.ID, args.Offset, args.Limit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(databases, 0, 0, 0, nil)
|
||||
fmt.Println("TotalCount: ", totalCount)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceDBListOptions{}, "mysql-instance-account-list", "List mysql instance accounts", func(cli *qcloud.SRegion, args *MySQLInstanceDBListOptions) error {
|
||||
accounts, totalCount, err := cli.DescribeMySQLAccounts(args.ID, args.Offset, args.Limit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(accounts, 0, 0, 0, nil)
|
||||
fmt.Println("TotalCount: ", totalCount)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceDBListOptions{}, "mysql-instance-backup-list", "List mysql instance backups", func(cli *qcloud.SRegion, args *MySQLInstanceDBListOptions) error {
|
||||
backups, totalCount, err := cli.DescribeMySQLBackups(args.ID, args.Offset, args.Limit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(backups, 0, 0, 0, nil)
|
||||
fmt.Println("TotalCount: ", totalCount)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceIdOptions{}, "mysql-instance-show", "Show mysql instance", func(cli *qcloud.SRegion, args *MySQLInstanceIdOptions) error {
|
||||
result, err := cli.DescribeMySQLDBInstanceInfo(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MySQLRenewOptions struct {
|
||||
MySQLInstanceIdOptions
|
||||
MONTH int `choices:"1|2|3|4|5|6|7|8|9|10|11|12|24|36"`
|
||||
}
|
||||
|
||||
shellutils.R(&MySQLRenewOptions{}, "mysql-instance-renew", "Renew mysql instance", func(cli *qcloud.SRegion, args *MySQLRenewOptions) error {
|
||||
return cli.RenewMySQLDBInstance(args.ID, args.MONTH)
|
||||
})
|
||||
|
||||
shellutils.R(&MySQLInstanceIdOptions{}, "mysql-instance-backup-create", "Create mysql instance backup", func(cli *qcloud.SRegion, args *MySQLInstanceIdOptions) error {
|
||||
backup, err := cli.CreateMySQLBackup(args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(backup)
|
||||
return nil
|
||||
})
|
||||
|
||||
type RestAccountPasswordOptions struct {
|
||||
INSTANCE_ID string
|
||||
PASSWORD string
|
||||
USER string
|
||||
Host string `default:"%"`
|
||||
}
|
||||
|
||||
shellutils.R(&RestAccountPasswordOptions{}, "mysql-account-reset-password", "Reset mysql account password", func(cli *qcloud.SRegion, args *RestAccountPasswordOptions) error {
|
||||
return cli.ModifyMySQLAccountPassword(args.INSTANCE_ID, args.PASSWORD, map[string]string{args.USER: args.Host})
|
||||
})
|
||||
|
||||
type MySQLAccountPrivilegeShowOptions struct {
|
||||
INSTANCE_ID string
|
||||
USER string
|
||||
Host string `default:"%"`
|
||||
}
|
||||
|
||||
shellutils.R(&MySQLAccountPrivilegeShowOptions{}, "mysql-account-privilege-show", "Show account privileges", func(cli *qcloud.SRegion, args *MySQLAccountPrivilegeShowOptions) error {
|
||||
result, err := cli.DescribeAccountPrivileges(args.INSTANCE_ID, args.USER, args.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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 shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type PostgreSQLProductListOptions struct {
|
||||
}
|
||||
shellutils.R(&PostgreSQLProductListOptions{}, "postgre-product-list", "List postgre sql products", func(cli *qcloud.SRegion, args *PostgreSQLProductListOptions) error {
|
||||
products, err := cli.DescribeProductConfig()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DescribeProductConfig")
|
||||
}
|
||||
printList(products, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SPostgreSQLSkuListOptions struct {
|
||||
}
|
||||
|
||||
shellutils.R(&SPostgreSQLSkuListOptions{}, "postgre-sku-list", "List postgre sql skus", func(cli *qcloud.SRegion, args *SPostgreSQLSkuListOptions) error {
|
||||
skus, err := cli.ListPostgreSQLSkus()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ListPostgreSQLSkus")
|
||||
}
|
||||
printList(skus, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// 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 shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SQLServerSQLProductListOptions struct {
|
||||
ZONE string
|
||||
}
|
||||
shellutils.R(&SQLServerSQLProductListOptions{}, "sqlserver-product-list", "List sql server products", func(cli *qcloud.SRegion, args *SQLServerSQLProductListOptions) error {
|
||||
products, err := cli.DescribeSqlServerProductConfig(args.ZONE)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DescribeProductConfig")
|
||||
}
|
||||
printList(products, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SSQLServerSQLSkuListOptions struct {
|
||||
}
|
||||
|
||||
shellutils.R(&SSQLServerSQLSkuListOptions{}, "sqlserver-sku-list", "List sqlserver skus", func(cli *qcloud.SRegion, args *SSQLServerSQLSkuListOptions) error {
|
||||
skus, err := cli.ListSQLServerSkus()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ListSQLServerSkus")
|
||||
}
|
||||
printList(skus, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user