From 809448134d9b3121486f4c4814a58f9ed587a636 Mon Sep 17 00:00:00 2001 From: Qu Xuan Date: Mon, 12 Jul 2021 14:54:38 +0800 Subject: [PATCH] fix(region): add qcloud tdsql --- pkg/apis/compute/dbinstance_const.go | 1 + pkg/multicloud/qcloud/dbinstance.go | 26 +- pkg/multicloud/qcloud/qcloud.go | 16 + pkg/multicloud/qcloud/rds_mysql.go | 20 ++ pkg/multicloud/qcloud/rds_tdsql.go | 389 ++++++++++++++++++++++++ pkg/multicloud/qcloud/region.go | 5 + pkg/multicloud/qcloud/shell/tdsql.go | 36 +++ pkg/multicloud/qcloud/tdsql_account.go | 99 ++++++ pkg/multicloud/qcloud/tdsql_database.go | 84 +++++ 9 files changed, 663 insertions(+), 13 deletions(-) create mode 100644 pkg/multicloud/qcloud/rds_tdsql.go create mode 100644 pkg/multicloud/qcloud/shell/tdsql.go create mode 100644 pkg/multicloud/qcloud/tdsql_account.go create mode 100644 pkg/multicloud/qcloud/tdsql_database.go diff --git a/pkg/apis/compute/dbinstance_const.go b/pkg/apis/compute/dbinstance_const.go index 0ed7b0f237..e20ab29db7 100644 --- a/pkg/apis/compute/dbinstance_const.go +++ b/pkg/apis/compute/dbinstance_const.go @@ -114,6 +114,7 @@ const ( QCLOUD_DBINSTANCE_CATEGORY_BASIC = "basic" //基础版 QCLOUD_DBINSTANCE_CATEGORY_HA = "ha" //高可用 QCLOUD_DBINSTANCE_CATEGORY_FINANCE = "fe" //金融版 + QCLOUD_DBINSTANCE_CATEGORY_TDSQL = "tdsql" //TDSQL //华为云实例类型 HUAWEI_DBINSTANCE_CATEGORY_HA = "ha" //主备 diff --git a/pkg/multicloud/qcloud/dbinstance.go b/pkg/multicloud/qcloud/dbinstance.go index 3ccf13356b..296dd54cfc 100644 --- a/pkg/multicloud/qcloud/dbinstance.go +++ b/pkg/multicloud/qcloud/dbinstance.go @@ -25,32 +25,32 @@ import ( 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 - } + mysqls, err := self.GetIMySQLs() + if err != nil { + return nil, errors.Wrapf(err, "GetIMySQLs") } - for i := range mysql { - mysql[i].region = self - ret = append(ret, &mysql[i]) + ret = append(ret, mysqls...) + tdsqls, err := self.GetITDSQLs() + if err != nil { + return nil, errors.Wrapf(err, "GetITDSQLs") } + ret = append(ret, tdsqls...) return ret, nil } func (self *SRegion) GetIDBInstanceById(id string) (cloudprovider.ICloudDBInstance, error) { if strings.HasPrefix(id, "cdb") { return self.GetMySQLInstanceById(id) + } else if strings.HasPrefix(id, "tdsqlshard") { + return self.GetTDSQL(id) } return nil, cloudprovider.ErrNotFound } func (self *SRegion) CreateIDBInstance(opts *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) { + if opts.Category == api.QCLOUD_DBINSTANCE_CATEGORY_TDSQL { + return nil, cloudprovider.ErrNotImplemented + } switch opts.Engine { case api.DBINSTANCE_TYPE_MYSQL: rds, err := self.CreateMySQLDBInstance(opts) diff --git a/pkg/multicloud/qcloud/qcloud.go b/pkg/multicloud/qcloud/qcloud.go index e0778d1b57..04df0b0707 100644 --- a/pkg/multicloud/qcloud/qcloud.go +++ b/pkg/multicloud/qcloud/qcloud.go @@ -65,6 +65,7 @@ const ( QCLOUD_CDN_API_VERSION = "2018-06-06" QCLOUD_MONGODB_API_VERSION = "2019-07-25" QCLOUD_ES_API_VERSION = "2018-04-16" + QCLOUD_DCDB_API_VERSION = "2018-04-11" ) type QcloudClientConfig struct { @@ -185,6 +186,12 @@ func redisRequest(client *common.Client, apiName string, params map[string]strin return _jsonRequest(client, domain, QCLOUD_REDIS_API_VERSION, apiName, params, debug, true) } +// tdsql +func dcdbRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) { + domain := apiDomain("dcdb", params) + return _jsonRequest(client, domain, QCLOUD_DCDB_API_VERSION, apiName, params, debug, true) +} + // mongodb func mongodbRequest(client *common.Client, apiName string, params map[string]string, debug bool) (jsonutils.JSONObject, error) { domain := apiDomain("mongodb", params) @@ -653,6 +660,15 @@ func (client *SQcloudClient) redisRequest(apiName string, params map[string]stri return redisRequest(cli, apiName, params, client.debug) } +func (client *SQcloudClient) dcdbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { + cli, err := client.getDefaultClient() + if err != nil { + return nil, err + } + + return dcdbRequest(cli, apiName, params, client.debug) +} + func (client *SQcloudClient) mongodbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { cli, err := client.getDefaultClient() if err != nil { diff --git a/pkg/multicloud/qcloud/rds_mysql.go b/pkg/multicloud/qcloud/rds_mysql.go index b104816349..1f24462d12 100644 --- a/pkg/multicloud/qcloud/rds_mysql.go +++ b/pkg/multicloud/qcloud/rds_mysql.go @@ -912,3 +912,23 @@ func (self *SMySQLInstance) GetTags() (map[string]string, error) { func (self *SMySQLInstance) SetTags(tags map[string]string, replace bool) error { return self.region.SetResourceTags("cdb", "instanceId", []string{self.InstanceId}, tags, replace) } + +func (self *SRegion) GetIMySQLs() ([]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 +} diff --git a/pkg/multicloud/qcloud/rds_tdsql.go b/pkg/multicloud/qcloud/rds_tdsql.go new file mode 100644 index 0000000000..a1acdb0c9e --- /dev/null +++ b/pkg/multicloud/qcloud/rds_tdsql.go @@ -0,0 +1,389 @@ +// 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" + "time" + + "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + + billing_api "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" +) + +type STDSQL struct { + multicloud.SVirtualResourceBase + multicloud.SBillingBase + multicloud.QcloudTags + region *SRegion + + AppId int `json:"AppId"` + AutoRenewFlag int `json:"AutoRenewFlag"` + CPU int `json:"Cpu"` + CreateTime time.Time `json:"CreateTime"` + DbEngine string `json:"DbEngine"` + DbVersion string `json:"DbVersion"` + DcnDstNum int `json:"DcnDstNum"` + DcnFlag int `json:"DcnFlag"` + DcnStatus int `json:"DcnStatus"` + ExclusterId string `json:"ExclusterId"` + Id int `json:"Id"` + InstanceId string `json:"InstanceId"` + InstanceName string `json:"InstanceName"` + InstanceType int `json:"InstanceType"` + Ipv6Flag int `json:"Ipv6Flag"` + IsAuditSupported int `json:"IsAuditSupported"` + IsTmp int `json:"IsTmp"` + IsolatedTimestamp string `json:"IsolatedTimestamp"` + Locker int `json:"Locker"` + Memory int `json:"Memory"` + NodeCount int `json:"NodeCount"` + Paymode string `json:"Paymode"` + PeriodEndTime string `json:"PeriodEndTime"` + Pid int `json:"Pid"` + ProjectId int `json:"ProjectId"` + Region string `json:"Region"` + ShardCount int `json:"ShardCount"` + ShardDetail []ShardDetail `json:"ShardDetail"` + Status int `json:"Status"` + StatusDesc string `json:"StatusDesc"` + Storage int `json:"Storage"` + SubnetId int `json:"SubnetId"` + Uin string `json:"Uin"` + UniqueSubnetId string `json:"UniqueSubnetId"` + UniqueVpcId string `json:"UniqueVpcId"` + UpdateTime string `json:"UpdateTime"` + Vip string `json:"Vip"` + Vipv6 string `json:"Vipv6"` + VpcId int `json:"VpcId"` + Vport int `json:"Vport"` + WanDomain string `json:"WanDomain"` + WanPort int `json:"WanPort"` + WanPortIpv6 int `json:"WanPortIpv6"` + WanStatus int `json:"WanStatus"` + WanStatusIpv6 int `json:"WanStatusIpv6"` + WanVip string `json:"WanVip"` + WanVipv6 string `json:"WanVipv6"` + Zone string `json:"Zone"` +} +type ShardDetail struct { + CPU int `json:"Cpu"` + Createtime string `json:"Createtime"` + Memory int `json:"Memory"` + NodeCount int `json:"NodeCount"` + Pid int `json:"Pid"` + ShardId int `json:"ShardId"` + ShardInstanceId string `json:"ShardInstanceId"` + ShardSerialId string `json:"ShardSerialId"` + Status int `json:"Status"` + Storage int `json:"Storage"` +} + +func (self *STDSQL) GetName() string { + return self.InstanceName +} + +func (self *STDSQL) GetId() string { + return self.InstanceId +} + +func (self *STDSQL) GetGlobalId() string { + return self.InstanceId +} + +// 0 创建中,1 流程处理中, 2 运行中,3 实例未初始化,-1 实例已隔离,-2 实例已删除,4 实例初始化中,5 实例删除中,6 实例重启中,7 数据迁移中 +func (self *STDSQL) GetStatus() string { + switch self.Status { + case 0, 1, 3, 4: + return api.DBINSTANCE_DEPLOYING + case 2: + return api.DBINSTANCE_RUNNING + case -1, -2, 5: + return api.DBINSTANCE_DELETING + case 6: + return api.DBINSTANCE_REBOOTING + case 7: + return api.DBINSTANCE_MIGRATING + default: + return fmt.Sprintf("%d", self.Status) + } +} + +func (self *STDSQL) GetPort() int { + return self.Vport +} + +func (self *STDSQL) GetVmemSizeMB() int { + return self.Memory * 1024 +} + +func (self *STDSQL) GetDiskSizeGB() int { + return self.Storage +} + +func (self *STDSQL) GetVcpuCount() int { + return self.CPU +} + +func (self *STDSQL) GetCreatedAt() time.Time { + return self.CreateTime.Add(time.Hour * -8) +} + +func (self *STDSQL) GetBillingType() string { + return self.Paymode +} + +func (self *STDSQL) GetProjectId() string { + return fmt.Sprintf("%d", self.ProjectId) +} + +func (self *STDSQL) Refresh() error { + sql, err := self.region.GetTDSQL(self.InstanceId) + if err != nil { + return err + } + return jsonutils.Update(self, sql) +} + +func (self *STDSQL) Reboot() error { + return cloudprovider.ErrNotSupported +} + +func (self *STDSQL) GetMasterInstanceId() string { + return "" +} + +func (self *STDSQL) GetSecurityGroupIds() ([]string, error) { + ret := []string{} + groups, err := self.region.GetTDSQLSecurityGroups(self.InstanceId) + if err != nil { + return ret, err + } + for i := range groups { + ret = append(ret, groups[i].SecurityGroupId) + } + return ret, nil +} + +func (self *STDSQL) SetSecurityGroups(ids []string) error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) GetEngine() string { + return self.DbEngine +} + +func (self *STDSQL) GetEngineVersion() string { + return self.DbVersion +} + +func (self *STDSQL) GetInstanceType() string { + return fmt.Sprintf("%dC%dG", self.GetVcpuCount(), self.GetVmemSizeMB()/1024) +} + +func (self *STDSQL) ChangeConfig(ctx context.Context, opts *cloudprovider.SManagedDBInstanceChangeConfig) error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) ClosePublicConnection() error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) OpenPublicConnection() error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) CreateAccount(opts *cloudprovider.SDBInstanceAccountCreateConfig) error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) CreateDatabase(opts *cloudprovider.SDBInstanceDatabaseCreateConfig) error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) CreateIBackup(opts *cloudprovider.SDBInstanceBackupCreateConfig) (string, error) { + return "", cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) GetMaintainTime() string { + return "" +} + +func (self *STDSQL) GetStorageType() string { + return "" +} + +func (self *STDSQL) GetIVpcId() string { + return self.UniqueVpcId +} + +func (self *STDSQL) Delete() error { + if self.GetBillingType() == billing_api.BILLING_TYPE_PREPAID { + return self.region.DeletePrepaidTDSQL(self.InstanceId) + } + return self.region.DeletePostpaidTDSQL(self.InstanceId) +} + +func (self *STDSQL) GetCategory() string { + return api.QCLOUD_DBINSTANCE_CATEGORY_TDSQL +} + +func (self *STDSQL) GetConnectionStr() string { + if len(self.WanDomain) > 0 { + return fmt.Sprintf("%s:%d", self.WanDomain, self.WanPort) + } + return "" +} + +func (self *STDSQL) GetInternalConnectionStr() string { + if len(self.Vip) > 0 { + return fmt.Sprintf("%s:%d", self.Vip, self.Vport) + } + return "" +} + +func (self *STDSQL) GetZone1Id() string { + return self.Zone +} + +func (self *STDSQL) GetZone2Id() string { + return "" +} + +func (self *STDSQL) GetZone3Id() string { + return "" +} + +func (self *STDSQL) RecoveryFromBackup(conf *cloudprovider.SDBInstanceRecoveryConfig) error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQL) GetDBNetworks() ([]cloudprovider.SDBInstanceNetwork, error) { + ret := []cloudprovider.SDBInstanceNetwork{} + if len(self.Vip) > 0 && len(self.UniqueSubnetId) > 0 { + ret = append(ret, cloudprovider.SDBInstanceNetwork{NetworkId: self.UniqueSubnetId, IP: self.Vip}) + } + return ret, nil +} + +func (self *SRegion) GetTDSQL(id string) (*STDSQL, error) { + sqls, _, err := self.GetTDSQLs([]string{id}, 1, 0) + if err != nil { + return nil, errors.Wrapf(err, "GetTDSQLs") + } + for i := range sqls { + if sqls[i].InstanceId == id { + sqls[i].region = self + return &sqls[i], nil + } + } + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "id: [%s]", id) +} + +func (self *SRegion) GetTDSQLs(ids []string, limit, offset int) ([]STDSQL, int, error) { + if limit < 1 || limit > 100 { + limit = 100 + } + params := map[string]string{ + "Limit": fmt.Sprintf("%d", limit), + "Offset": fmt.Sprintf("%d", offset), + } + for idx, id := range ids { + params[fmt.Sprintf("InstanceIds.%d", idx)] = id + } + resp, err := self.dcdbRequest("DescribeDCDBInstances", params) + if err != nil { + return nil, 0, errors.Wrapf(err, "DescribeDCDBInstances") + } + ret := []STDSQL{} + err = resp.Unmarshal(&ret, "Instances") + if err != nil { + return nil, 0, errors.Wrapf(err, "resp.Unmarshal") + } + totalCount, _ := resp.Float("TotalCount") + return ret, int(totalCount), nil +} + +func (self *SRegion) GetITDSQLs() ([]cloudprovider.ICloudDBInstance, error) { + ret := []cloudprovider.ICloudDBInstance{} + for { + part, total, err := self.GetTDSQLs(nil, 100, len(ret)) + if err != nil { + return nil, errors.Wrapf(err, "GetTDSQLs") + } + for i := range part { + part[i].region = self + ret = append(ret, &part[i]) + } + if len(ret) >= total { + break + } + } + return ret, nil +} + +type STDSQLSecurityGroup struct { + CreateTime string `json:"CreateTime"` + ProjectID int `json:"ProjectId"` + SecurityGroupId string `json:"SecurityGroupId"` + SecurityGroupName string `json:"SecurityGroupName"` + SecurityGroupRemark string `json:"SecurityGroupRemark"` +} + +func (self *SRegion) GetTDSQLSecurityGroups(id string) ([]STDSQLSecurityGroup, error) { + params := map[string]string{ + "Product": "dcdb", + "InstanceId": id, + } + resp, err := self.dcdbRequest("DescribeDBSecurityGroups", params) + if err != nil { + return nil, errors.Wrapf(err, "DescribeDBSecurityGroups") + } + ret := []STDSQLSecurityGroup{} + err = resp.Unmarshal(&ret, "Groups") + if err != nil { + return nil, errors.Wrapf(err, "resp.Unmarshal") + } + return ret, nil +} + +func (self *STDSQL) GetIDBInstanceBackups() ([]cloudprovider.ICloudDBInstanceBackup, error) { + return []cloudprovider.ICloudDBInstanceBackup{}, nil +} + +func (self *STDSQL) GetIDBInstanceParameters() ([]cloudprovider.ICloudDBInstanceParameter, error) { + return nil, cloudprovider.ErrNotImplemented +} + +func (self *SRegion) DeletePostpaidTDSQL(id string) error { + params := map[string]string{ + "InstanceId": id, + } + _, err := self.dcdbRequest("DestroyHourDCDBInstance", params) + return errors.Wrapf(err, "DestroyHourDCDBInstance") +} + +func (self *SRegion) DeletePrepaidTDSQL(id string) error { + params := map[string]string{ + "InstanceId": id, + } + _, err := self.dcdbRequest("DestroyDCDBInstance", params) + return errors.Wrapf(err, "DestroyDCDBInstance") +} diff --git a/pkg/multicloud/qcloud/region.go b/pkg/multicloud/qcloud/region.go index 19a58891d9..4ed2f2ba14 100644 --- a/pkg/multicloud/qcloud/region.go +++ b/pkg/multicloud/qcloud/region.go @@ -686,6 +686,11 @@ func (self *SRegion) redisRequest(apiName string, params map[string]string) (jso return self.client.redisRequest(apiName, params) } +func (self *SRegion) dcdbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { + params["Region"] = self.Region + return self.client.dcdbRequest(apiName, params) +} + func (self *SRegion) mongodbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) { params["Region"] = self.Region return self.client.mongodbRequest(apiName, params) diff --git a/pkg/multicloud/qcloud/shell/tdsql.go b/pkg/multicloud/qcloud/shell/tdsql.go new file mode 100644 index 0000000000..e88bd12a21 --- /dev/null +++ b/pkg/multicloud/qcloud/shell/tdsql.go @@ -0,0 +1,36 @@ +// 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/onecloud/pkg/multicloud/qcloud" + "yunion.io/x/onecloud/pkg/util/shellutils" +) + +func init() { + type TDSQLListOptions struct { + Ids []string + Limit int + Offset int + } + shellutils.R(&TDSQLListOptions{}, "tdsql-list", "List tdsql", func(cli *qcloud.SRegion, args *TDSQLListOptions) error { + tdsqls, _, err := cli.GetTDSQLs(args.Ids, args.Limit, args.Offset) + if err != nil { + return err + } + printList(tdsqls, 0, 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/multicloud/qcloud/tdsql_account.go b/pkg/multicloud/qcloud/tdsql_account.go new file mode 100644 index 0000000000..76e086e3e5 --- /dev/null +++ b/pkg/multicloud/qcloud/tdsql_account.go @@ -0,0 +1,99 @@ +// 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" + + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/multicloud" +) + +type STDSQLAccount struct { + multicloud.SDBInstanceAccountBase + multicloud.QcloudTags + rds *STDSQL + + UserName string + Host string + Description string + CreateTime string + UpdateTime string + ReadOnly int + DelayThresh int +} + +func (self *STDSQLAccount) GetName() string { + return self.UserName +} + +func (self *STDSQLAccount) GetHost() string { + return self.Host +} + +func (self *STDSQLAccount) Delete() error { + return self.rds.region.DeleteTDSQLAccount(self.rds.InstanceId, self.UserName, self.Host) +} + +func (self *STDSQLAccount) GrantPrivilege(database, privilege string) error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQLAccount) RevokePrivilege(database string) error { + return cloudprovider.ErrNotImplemented +} + +func (self *STDSQLAccount) GetIDBInstanceAccountPrivileges() ([]cloudprovider.ICloudDBInstanceAccountPrivilege, error) { + return nil, cloudprovider.ErrNotImplemented +} + +func (self *SRegion) GetTDSQLAccount(id string) ([]STDSQLAccount, error) { + params := map[string]string{ + "InstanceId": id, + } + resp, err := self.dcdbRequest("DescribeAccounts", params) + if err != nil { + return nil, errors.Wrapf(err, "DescribeAccounts") + } + ret := []STDSQLAccount{} + err = resp.Unmarshal(&ret, "Users") + if err != nil { + return nil, errors.Wrapf(err, "resp.Unmarshal") + } + return ret, nil +} + +func (self *STDSQL) GetIDBInstanceAccounts() ([]cloudprovider.ICloudDBInstanceAccount, error) { + accounts, err := self.region.GetTDSQLAccount(self.InstanceId) + if err != nil { + return nil, errors.Wrapf(err, "GetTDSQLAccount") + } + ret := []cloudprovider.ICloudDBInstanceAccount{} + for i := range accounts { + accounts[i].rds = self + ret = append(ret, &accounts[i]) + } + return ret, nil +} + +func (self *SRegion) DeleteTDSQLAccount(id, name, host string) error { + params := map[string]string{ + "InstanceId": id, + "UserName": name, + "Host": host, + } + _, err := self.dcdbRequest("DeleteAccount", params) + return errors.Wrapf(err, "DeleteAccount") +} diff --git a/pkg/multicloud/qcloud/tdsql_database.go b/pkg/multicloud/qcloud/tdsql_database.go new file mode 100644 index 0000000000..2555e7478d --- /dev/null +++ b/pkg/multicloud/qcloud/tdsql_database.go @@ -0,0 +1,84 @@ +// 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" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/multicloud" +) + +type STDSQLDatabase struct { + rds *STDSQL + multicloud.SResourceBase + multicloud.QcloudTags + + DbName string +} + +func (self *STDSQLDatabase) GetStatus() string { + return api.DBINSTANCE_DATABASE_RUNNING +} + +func (self *STDSQLDatabase) GetId() string { + return self.DbName +} + +func (self *STDSQLDatabase) GetName() string { + return self.DbName +} + +func (self *STDSQLDatabase) GetGlobalId() string { + return self.DbName +} + +func (self *STDSQLDatabase) GetCharacterSet() string { + return "" +} + +func (self *STDSQLDatabase) Delete() error { + return cloudprovider.ErrNotSupported +} + +func (self *SRegion) GetTDSQLDatabases(id string) ([]STDSQLDatabase, error) { + params := map[string]string{ + "InstanceId": id, + } + resp, err := self.dcdbRequest("DescribeDatabases", params) + if err != nil { + return nil, errors.Wrapf(err, "DescribeDatabases") + } + ret := []STDSQLDatabase{} + err = resp.Unmarshal(&ret, "Databases") + if err != nil { + return nil, errors.Wrapf(err, "resp.Unmarshal") + } + return ret, nil +} + +func (self *STDSQL) GetIDBInstanceDatabases() ([]cloudprovider.ICloudDBInstanceDatabase, error) { + dbs, err := self.region.GetTDSQLDatabases(self.InstanceId) + if err != nil { + return nil, errors.Wrapf(err, "GetTDSQLDatabases") + } + ret := []cloudprovider.ICloudDBInstanceDatabase{} + for i := range dbs { + dbs[i].rds = self + ret = append(ret, &dbs[i]) + } + return ret, nil +}