dbinstance.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package apsara
  15. import (
  16. "context"
  17. "fmt"
  18. "strings"
  19. "time"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/util/billing"
  24. "yunion.io/x/pkg/util/rand"
  25. "yunion.io/x/pkg/utils"
  26. api "yunion.io/x/cloudmux/pkg/apis/compute"
  27. "yunion.io/x/cloudmux/pkg/cloudprovider"
  28. "yunion.io/x/cloudmux/pkg/multicloud"
  29. )
  30. type SReadOnlyDBInstanceIds struct {
  31. ReadOnlyDBInstanceId []string
  32. }
  33. type SDBInstanceId struct {
  34. DBInstanceId []string
  35. }
  36. type SDBInstanceExtra struct {
  37. DBInstanceId SDBInstanceId
  38. }
  39. type SDBInstance struct {
  40. multicloud.SDBInstanceBase
  41. ApsaraTags
  42. netInfo []SDBInstanceNetwork
  43. region *SRegion
  44. AccountMaxQuantity int
  45. AccountType string
  46. CanTempUpgrade bool
  47. Category string
  48. AvailabilityValue string
  49. DBInstanceDescription string
  50. DBInstanceId string
  51. ConnectionMode string
  52. ConnectionString string
  53. CurrentKernelVersion string
  54. DBInstanceCPU int
  55. CreateTime time.Time
  56. DBInstanceClass string
  57. DBInstanceClassType string
  58. DBInstanceNetType string
  59. DBInstanceStatus string
  60. DBInstanceType string
  61. DBInstanceDiskUsed int64
  62. DBInstanceStorage int
  63. DBInstanceStorageType string
  64. MasterInstanceId string
  65. DBInstanceMemory int
  66. DBMaxQuantity int
  67. IPType string
  68. LatestKernelVersion string
  69. DispenseMode string
  70. Engine string
  71. EngineVersion string
  72. ExpireTime time.Time
  73. InstanceNetworkType string
  74. LockMode string
  75. LockReason string
  76. MutriORsignle bool
  77. MaintainTime string
  78. MaxConnections int
  79. MaxIOPS int
  80. Port int
  81. PayType TChargeType
  82. ReadOnlyDBInstanceIds SReadOnlyDBInstanceIds
  83. RegionId string
  84. VSwitchId string
  85. VpcCloudInstanceId string
  86. VpcId string
  87. ZoneId string
  88. Extra SDBInstanceExtra
  89. SecurityIPList string
  90. SecurityIPMode string
  91. SupportCreateSuperAccount string
  92. SupportUpgradeAccountType string
  93. TempUpgradeTimeEnd time.Time
  94. TempUpgradeTimeStart time.Time
  95. DepartmentInfo
  96. }
  97. func (rds *SDBInstance) GetName() string {
  98. if len(rds.DBInstanceDescription) > 0 {
  99. return rds.DBInstanceDescription
  100. }
  101. return rds.DBInstanceId
  102. }
  103. func (rds *SDBInstance) GetId() string {
  104. return rds.DBInstanceId
  105. }
  106. func (rds *SDBInstance) GetGlobalId() string {
  107. return rds.GetId()
  108. }
  109. // Creating 创建中
  110. // Running 使用中
  111. // Deleting 删除中
  112. // Rebooting 重启中
  113. // DBInstanceClassChanging 升降级中
  114. // TRANSING 迁移中
  115. // EngineVersionUpgrading 迁移版本中
  116. // TransingToOthers 迁移数据到其他RDS中
  117. // GuardDBInstanceCreating 生产灾备实例中
  118. // Restoring 备份恢复中
  119. // Importing 数据导入中
  120. // ImportingFromOthers 从其他RDS实例导入数据中
  121. // DBInstanceNetTypeChanging 内外网切换中
  122. // GuardSwitching 容灾切换中
  123. // INS_CLONING 实例克隆中
  124. func (rds *SDBInstance) GetStatus() string {
  125. switch rds.DBInstanceStatus {
  126. case "Creating", "GuardDBInstanceCreating", "DBInstanceNetTypeChanging", "GuardSwitching", "NET_CREATING", "NET_DELETING":
  127. return api.DBINSTANCE_DEPLOYING
  128. case "DBInstanceClassChanging":
  129. return api.DBINSTANCE_CHANGE_CONFIG
  130. case "Running":
  131. return api.DBINSTANCE_RUNNING
  132. case "Deleting":
  133. return api.DBINSTANCE_DELETING
  134. case "Rebooting":
  135. return api.DBINSTANCE_REBOOTING
  136. case "TRANSING", "EngineVersionUpgrading", "TransingToOthers":
  137. return api.DBINSTANCE_MIGRATING
  138. case "Restoring":
  139. return api.DBINSTANCE_RESTORING
  140. case "Importing", "ImportingFromOthers":
  141. return api.DBINSTANCE_IMPORTING
  142. case "INS_CLONING":
  143. return api.DBINSTANCE_CLONING
  144. default:
  145. log.Errorf("Unknown dbinstance status %s", rds.DBInstanceStatus)
  146. return api.DBINSTANCE_UNKNOWN
  147. }
  148. }
  149. func (rds *SDBInstance) GetBillingType() string {
  150. return convertChargeType(rds.PayType)
  151. }
  152. func (rds *SDBInstance) GetCreatedAt() time.Time {
  153. return rds.CreateTime
  154. }
  155. func (rds *SDBInstance) GetStorageType() string {
  156. return rds.DBInstanceStorageType
  157. }
  158. func (rds *SDBInstance) GetIops() int {
  159. return rds.MaxIOPS
  160. }
  161. func (rds *SDBInstance) GetEngine() string {
  162. switch rds.Engine {
  163. case "MySQL":
  164. return api.DBINSTANCE_TYPE_MYSQL
  165. case "SQLServer":
  166. return api.DBINSTANCE_TYPE_SQLSERVER
  167. case "PostgreSQL":
  168. return api.DBINSTANCE_TYPE_POSTGRESQL
  169. case "PPAS":
  170. return api.DBINSTANCE_TYPE_PPAS
  171. case "MariaDB":
  172. return api.DBINSTANCE_TYPE_MARIADB
  173. }
  174. return rds.Engine
  175. }
  176. func (rds *SDBInstance) GetEngineVersion() string {
  177. return rds.EngineVersion
  178. }
  179. func (rds *SDBInstance) GetInstanceType() string {
  180. return rds.DBInstanceClass
  181. }
  182. func (rds *SDBInstance) GetCategory() string {
  183. switch rds.Category {
  184. case "Basic":
  185. return api.ALIYUN_DBINSTANCE_CATEGORY_BASIC
  186. case "HighAvailability":
  187. return api.ALIYUN_DBINSTANCE_CATEGORY_HA
  188. case "AlwaysOn":
  189. return api.ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON
  190. case "Finance":
  191. return api.ALIYUN_DBINSTANCE_CATEGORY_FINANCE
  192. }
  193. return rds.Category
  194. }
  195. func (rds *SDBInstance) GetVcpuCount() int {
  196. if rds.DBInstanceCPU == 0 {
  197. rds.Refresh()
  198. }
  199. return rds.DBInstanceCPU
  200. }
  201. func (rds *SDBInstance) GetVmemSizeMB() int {
  202. if rds.DBInstanceMemory == 0 {
  203. rds.Refresh()
  204. }
  205. return rds.DBInstanceMemory
  206. }
  207. func (rds *SDBInstance) GetDiskSizeGB() int {
  208. if rds.DBInstanceStorage == 0 {
  209. rds.Refresh()
  210. }
  211. return rds.DBInstanceStorage
  212. }
  213. func (rds *SDBInstance) GetDiskSizeUsedMB() int {
  214. if rds.DBInstanceDiskUsed == 0 {
  215. rds.Refresh()
  216. }
  217. return int(rds.DBInstanceDiskUsed / 1024 / 1024)
  218. }
  219. func (rds *SDBInstance) GetPort() int {
  220. if rds.Port == 0 {
  221. rds.Refresh()
  222. }
  223. return rds.Port
  224. }
  225. func (rds *SDBInstance) GetMaintainTime() string {
  226. return rds.MaintainTime
  227. }
  228. func (rds *SDBInstance) GetIVpcId() string {
  229. return rds.VpcId
  230. }
  231. func (rds *SDBInstance) Refresh() error {
  232. instance, err := rds.region.GetDBInstanceDetail(rds.DBInstanceId)
  233. if err != nil {
  234. return err
  235. }
  236. return jsonutils.Update(rds, instance)
  237. }
  238. func (rds *SDBInstance) getZoneId(index int) string {
  239. zoneId := rds.getZone(index)
  240. if len(zoneId) > 0 {
  241. zone, err := rds.region.getZoneById(zoneId)
  242. if err != nil {
  243. log.Errorf("failed to found zone %s for rds %s", zoneId, rds.GetName())
  244. return ""
  245. }
  246. return zone.GetGlobalId()
  247. }
  248. return ""
  249. }
  250. func (rds *SDBInstance) GetZone1Id() string {
  251. return rds.getZoneId(1)
  252. }
  253. func (rds *SDBInstance) GetZone2Id() string {
  254. return rds.getZoneId(2)
  255. }
  256. func (rds *SDBInstance) GetZone3Id() string {
  257. return rds.getZoneId(3)
  258. }
  259. func (rds *SDBInstance) getZone(index int) string {
  260. zoneStr := strings.Replace(rds.ZoneId, ")", "", -1)
  261. zoneInfo := strings.Split(zoneStr, ",")
  262. if len(zoneInfo) < index {
  263. return ""
  264. }
  265. zone := zoneInfo[index-1]
  266. zoneCode := zone[len(zone)-1]
  267. if strings.HasPrefix(rds.ZoneId, fmt.Sprintf("%s-", rds.RegionId)) {
  268. return fmt.Sprintf("%s-%s", rds.RegionId, string(zoneCode))
  269. }
  270. return fmt.Sprintf("%s%s", rds.RegionId, string(zoneCode))
  271. }
  272. func (rds *SDBInstance) GetDBNetworks() ([]cloudprovider.SDBInstanceNetwork, error) {
  273. netInfo, err := rds.region.GetDBInstanceNetInfo(rds.DBInstanceId)
  274. if err != nil {
  275. return nil, errors.Wrapf(err, "GetDBInstanceNetInfo")
  276. }
  277. networks := []cloudprovider.SDBInstanceNetwork{}
  278. for _, net := range netInfo {
  279. if net.IPType == "Private" {
  280. network := cloudprovider.SDBInstanceNetwork{}
  281. network.IP = net.IPAddress
  282. network.NetworkId = net.VSwitchId
  283. networks = append(networks, network)
  284. }
  285. }
  286. return networks, nil
  287. }
  288. func (rds *SDBInstance) fetchNetInfo() error {
  289. if len(rds.netInfo) > 0 {
  290. return nil
  291. }
  292. netInfo, err := rds.region.GetDBInstanceNetInfo(rds.DBInstanceId)
  293. if err != nil {
  294. return errors.Wrap(err, "GetDBInstanceNetInfo")
  295. }
  296. rds.netInfo = netInfo
  297. return nil
  298. }
  299. func (rds *SDBInstance) GetInternalConnectionStr() string {
  300. err := rds.fetchNetInfo()
  301. if err != nil {
  302. log.Errorf("failed to fetch netInfo error: %v", err)
  303. return ""
  304. }
  305. for _, net := range rds.netInfo {
  306. if net.IPType != "Public" {
  307. return net.ConnectionString
  308. }
  309. }
  310. return ""
  311. }
  312. func (rds *SDBInstance) GetConnectionStr() string {
  313. err := rds.fetchNetInfo()
  314. if err != nil {
  315. log.Errorf("failed to fetch netInfo error: %v", err)
  316. return ""
  317. }
  318. for _, net := range rds.netInfo {
  319. if net.IPType == "Public" {
  320. return net.ConnectionString
  321. }
  322. }
  323. return ""
  324. }
  325. func (region *SRegion) GetDBInstances(ids []string, offset int, limit int) ([]SDBInstance, int, error) {
  326. if limit > 50 || limit <= 0 {
  327. limit = 50
  328. }
  329. params := make(map[string]string)
  330. params["RegionId"] = region.RegionId
  331. params["PageSize"] = fmt.Sprintf("%d", limit)
  332. params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
  333. body, err := region.rdsRequest("DescribeDBInstances", params)
  334. if err != nil {
  335. return nil, 0, errors.Wrapf(err, "GetDBInstances")
  336. }
  337. instances := []SDBInstance{}
  338. err = body.Unmarshal(&instances, "Items", "DBInstance")
  339. if err != nil {
  340. return nil, 0, errors.Wrapf(err, "GetDBInstances.Unmarshal")
  341. }
  342. total, _ := body.Int("TotalRecordCount")
  343. return instances, int(total), nil
  344. }
  345. func (region *SRegion) GetIDBInstanceById(instanceId string) (cloudprovider.ICloudDBInstance, error) {
  346. rds, err := region.GetDBInstanceDetail(instanceId)
  347. if err != nil {
  348. return nil, err
  349. }
  350. rds.region = region
  351. return rds, nil
  352. }
  353. func (region *SRegion) GetIDBInstances() ([]cloudprovider.ICloudDBInstance, error) {
  354. instances := []SDBInstance{}
  355. for {
  356. part, total, err := region.GetDBInstances([]string{}, len(instances), 50)
  357. if err != nil {
  358. return nil, err
  359. }
  360. instances = append(instances, part...)
  361. if len(instances) >= total || len(part) == 0 {
  362. break
  363. }
  364. }
  365. idbinstances := []cloudprovider.ICloudDBInstance{}
  366. for i := 0; i < len(instances); i++ {
  367. instances[i].region = region
  368. idbinstances = append(idbinstances, &instances[i])
  369. }
  370. return idbinstances, nil
  371. }
  372. func (region *SRegion) GetDBInstanceDetail(instanceId string) (*SDBInstance, error) {
  373. if len(instanceId) == 0 {
  374. return nil, cloudprovider.ErrNotFound
  375. }
  376. params := map[string]string{}
  377. params["RegionId"] = region.RegionId
  378. params["DBInstanceId"] = instanceId
  379. body, err := region.rdsRequest("DescribeDBInstanceAttribute", params)
  380. if err != nil {
  381. return nil, errors.Wrapf(err, "GetDBInstanceDetail")
  382. }
  383. instances := []SDBInstance{}
  384. err = body.Unmarshal(&instances, "Items", "DBInstanceAttribute")
  385. if err != nil {
  386. return nil, errors.Wrapf(err, "GetDBInstanceDetail.Unmarshal")
  387. }
  388. if len(instances) == 1 {
  389. instances[0].region = region
  390. return &instances[0], nil
  391. }
  392. if len(instances) == 0 {
  393. return nil, cloudprovider.ErrNotFound
  394. }
  395. return nil, cloudprovider.ErrDuplicateId
  396. }
  397. func (region *SRegion) DeleteDBInstance(instanceId string) error {
  398. params := map[string]string{}
  399. params["RegionId"] = region.RegionId
  400. params["DBInstanceId"] = instanceId
  401. _, err := region.rdsRequest("DeleteDBInstance", params)
  402. return err
  403. }
  404. type SDBInstanceWeight struct {
  405. }
  406. type SDBInstanceWeights struct {
  407. DBInstanceWeight []SDBInstanceWeight
  408. }
  409. type SsecurityIPGroup struct {
  410. }
  411. type SSecurityIPGroups struct {
  412. securityIPGroup []SsecurityIPGroup
  413. }
  414. type SDBInstanceNetwork struct {
  415. ConnectionString string
  416. ConnectionStringType string
  417. DBInstanceWeights SDBInstanceWeights
  418. IPAddress string
  419. IPType string
  420. Port int
  421. SecurityIPGroups SSecurityIPGroups
  422. Upgradeable string
  423. VPCId string
  424. VSwitchId string
  425. }
  426. func (network *SDBInstanceNetwork) GetGlobalId() string {
  427. return network.IPAddress
  428. }
  429. func (network *SDBInstanceNetwork) GetINetworkId() string {
  430. return network.VSwitchId
  431. }
  432. func (network *SDBInstanceNetwork) GetIP() string {
  433. return network.IPAddress
  434. }
  435. func (region *SRegion) GetDBInstanceNetInfo(instanceId string) ([]SDBInstanceNetwork, error) {
  436. params := map[string]string{}
  437. params["RegionId"] = region.RegionId
  438. params["DBInstanceId"] = instanceId
  439. body, err := region.rdsRequest("DescribeDBInstanceNetInfo", params)
  440. if err != nil {
  441. return nil, errors.Wrapf(err, "GetDBInstanceNetwork")
  442. }
  443. networks := []SDBInstanceNetwork{}
  444. err = body.Unmarshal(&networks, "DBInstanceNetInfos", "DBInstanceNetInfo")
  445. if err != nil {
  446. return nil, err
  447. }
  448. return networks, nil
  449. }
  450. func (rds *SDBInstance) GetIDBInstanceParameters() ([]cloudprovider.ICloudDBInstanceParameter, error) {
  451. parameters, err := rds.region.GetDBInstanceParameters(rds.DBInstanceId)
  452. if err != nil {
  453. return nil, err
  454. }
  455. iparameters := []cloudprovider.ICloudDBInstanceParameter{}
  456. for i := 0; i < len(parameters); i++ {
  457. iparameters = append(iparameters, &parameters[i])
  458. }
  459. return iparameters, nil
  460. }
  461. func (region *SRegion) GetIDBInstanceBackupById(backupId string) (cloudprovider.ICloudDBInstanceBackup, error) {
  462. backups, err := region.GetIDBInstanceBackups()
  463. if err != nil {
  464. return nil, errors.Wrap(err, "region.GetIDBInstanceBackups")
  465. }
  466. for _, backup := range backups {
  467. if backup.GetGlobalId() == backupId {
  468. return backup, nil
  469. }
  470. }
  471. return nil, cloudprovider.ErrNotFound
  472. }
  473. func (rds *SDBInstance) Reboot() error {
  474. return rds.region.RebootDBInstance(rds.DBInstanceId)
  475. }
  476. func (rds *SDBInstance) Delete() error {
  477. return rds.region.DeleteDBInstance(rds.DBInstanceId)
  478. }
  479. func (region *SRegion) RebootDBInstance(instanceId string) error {
  480. params := map[string]string{}
  481. params["RegionId"] = region.RegionId
  482. params["DBInstanceId"] = instanceId
  483. _, err := region.rdsRequest("RestartDBInstance", params)
  484. return err
  485. }
  486. func (rds *SDBInstance) GetIDBInstanceDatabases() ([]cloudprovider.ICloudDBInstanceDatabase, error) {
  487. databases := []SDBInstanceDatabase{}
  488. for {
  489. parts, total, err := rds.region.GetDBInstanceDatabases(rds.DBInstanceId, "", len(databases), 500)
  490. if err != nil {
  491. return nil, err
  492. }
  493. databases = append(databases, parts...)
  494. if len(databases) >= total {
  495. break
  496. }
  497. }
  498. idatabase := []cloudprovider.ICloudDBInstanceDatabase{}
  499. for i := 0; i < len(databases); i++ {
  500. databases[i].instance = rds
  501. idatabase = append(idatabase, &databases[i])
  502. }
  503. return idatabase, nil
  504. }
  505. func (rds *SDBInstance) GetIDBInstanceAccounts() ([]cloudprovider.ICloudDBInstanceAccount, error) {
  506. accounts := []SDBInstanceAccount{}
  507. for {
  508. parts, total, err := rds.region.GetDBInstanceAccounts(rds.DBInstanceId, len(accounts), 50)
  509. if err != nil {
  510. return nil, err
  511. }
  512. accounts = append(accounts, parts...)
  513. if len(accounts) >= total {
  514. break
  515. }
  516. }
  517. iaccounts := []cloudprovider.ICloudDBInstanceAccount{}
  518. for i := 0; i < len(accounts); i++ {
  519. accounts[i].instance = rds
  520. iaccounts = append(iaccounts, &accounts[i])
  521. }
  522. return iaccounts, nil
  523. }
  524. func (rds *SDBInstance) ChangeConfig(cxt context.Context, desc *cloudprovider.SManagedDBInstanceChangeConfig) error {
  525. return rds.region.ChangeDBInstanceConfig(rds.DBInstanceId, string(rds.PayType), desc)
  526. }
  527. func (region *SRegion) ChangeDBInstanceConfig(instanceId, payType string, desc *cloudprovider.SManagedDBInstanceChangeConfig) error {
  528. params := map[string]string{
  529. "RegionId": region.RegionId,
  530. "DBInstanceId": instanceId,
  531. "PayType": payType,
  532. "DBInstanceClass": desc.InstanceType,
  533. "DBInstanceStorage": fmt.Sprintf("%d", desc.DiskSizeGB),
  534. }
  535. _, err := region.rdsRequest("ModifyDBInstanceSpec", params)
  536. if err != nil {
  537. return errors.Wrap(err, "region.rdsRequest.ModifyDBInstanceSpec")
  538. }
  539. return nil
  540. }
  541. func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) {
  542. params := map[string]string{
  543. "RegionId": region.RegionId,
  544. "Engine": desc.Engine,
  545. "EngineVersion": desc.EngineVersion,
  546. "DBInstanceStorage": fmt.Sprintf("%d", desc.DiskSizeGB),
  547. "DBInstanceNetType": "Intranet",
  548. "PayType": "Postpaid",
  549. "SecurityIPList": "0.0.0.0/0",
  550. "DBInstanceDescription": desc.Name,
  551. "InstanceNetworkType": "VPC",
  552. "VPCId": desc.VpcId,
  553. "VSwitchId": desc.NetworkId,
  554. "DBInstanceStorageType": desc.StorageType,
  555. "DBInstanceClass": desc.InstanceType,
  556. "ZoneId": desc.ZoneId,
  557. "ClientToken": utils.GenRequestId(20),
  558. }
  559. switch desc.Category {
  560. case api.ALIYUN_DBINSTANCE_CATEGORY_HA:
  561. params["Category"] = "HighAvailability"
  562. case api.ALIYUN_DBINSTANCE_CATEGORY_BASIC:
  563. params["Category"] = "Basic"
  564. case api.ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON:
  565. params["Category"] = "AlwaysOn"
  566. case api.ALIYUN_DBINSTANCE_CATEGORY_FINANCE:
  567. params["Category"] = "Finance"
  568. }
  569. if len(desc.Address) > 0 {
  570. params["PrivateIpAddress"] = desc.Address
  571. }
  572. if len(desc.ProjectId) > 0 {
  573. params["ResourceGroupId"] = desc.ProjectId
  574. }
  575. if desc.BillingCycle != nil {
  576. params["PayType"] = "Prepaid"
  577. if desc.BillingCycle.GetMonths() > 0 {
  578. params["Period"] = "Month"
  579. params["UsedTime"] = fmt.Sprintf("%d", desc.BillingCycle.GetMonths())
  580. } else {
  581. params["Period"] = "Year"
  582. params["UsedTime"] = fmt.Sprintf("%d", desc.BillingCycle.GetYears())
  583. }
  584. params["AutoRenew"] = "False"
  585. }
  586. action := "CreateDBInstance"
  587. if len(desc.MasterInstanceId) > 0 {
  588. action = "CreateReadOnlyDBInstance"
  589. params["DBInstanceId"] = desc.MasterInstanceId
  590. }
  591. resp, err := region.rdsRequest(action, params)
  592. if err != nil {
  593. return nil, errors.Wrapf(err, "rdsRequest")
  594. }
  595. instanceId, err := resp.GetString("DBInstanceId")
  596. if err != nil {
  597. return nil, errors.Wrap(err, `resp.GetString("DBInstanceId")`)
  598. }
  599. region.SetResourceTags("rds", "INSTANCE", []string{instanceId}, desc.Tags, false)
  600. return region.GetIDBInstanceById(instanceId)
  601. }
  602. func (rds *SDBInstance) GetMasterInstanceId() string {
  603. if len(rds.MasterInstanceId) > 0 {
  604. return rds.MasterInstanceId
  605. }
  606. rds.Refresh()
  607. return rds.MasterInstanceId
  608. }
  609. func (region *SRegion) OpenPublicConnection(instanceId string) error {
  610. rds, err := region.GetDBInstanceDetail(instanceId)
  611. if err != nil {
  612. return err
  613. }
  614. params := map[string]string{
  615. "RegionId": region.RegionId,
  616. "ConnectionStringPrefix": rds.DBInstanceId + rand.String(3),
  617. "DBInstanceId": rds.DBInstanceId,
  618. "Port": fmt.Sprintf("%d", rds.Port),
  619. }
  620. _, err = rds.region.rdsRequest("AllocateInstancePublicConnection", params)
  621. if err != nil {
  622. return errors.Wrap(err, "rdsRequest(AllocateInstancePublicConnection)")
  623. }
  624. return nil
  625. }
  626. func (rds *SDBInstance) OpenPublicConnection() error {
  627. if url := rds.GetConnectionStr(); len(url) == 0 {
  628. err := rds.region.OpenPublicConnection(rds.DBInstanceId)
  629. if err != nil {
  630. return err
  631. }
  632. rds.netInfo = []SDBInstanceNetwork{}
  633. }
  634. return nil
  635. }
  636. func (region *SRegion) ClosePublicConnection(instanceId string) error {
  637. netInfo, err := region.GetDBInstanceNetInfo(instanceId)
  638. if err != nil {
  639. return errors.Wrap(err, "GetDBInstanceNetInfo")
  640. }
  641. for _, net := range netInfo {
  642. if net.IPType == "Public" {
  643. params := map[string]string{
  644. "RegionId": region.RegionId,
  645. "CurrentConnectionString": net.ConnectionString,
  646. "DBInstanceId": instanceId,
  647. }
  648. _, err = region.rdsRequest("ReleaseInstancePublicConnection", params)
  649. if err != nil {
  650. return errors.Wrap(err, "rdsRequest(ReleaseInstancePublicConnection)")
  651. }
  652. }
  653. }
  654. return nil
  655. }
  656. func (rds *SDBInstance) ClosePublicConnection() error {
  657. return rds.region.ClosePublicConnection(rds.DBInstanceId)
  658. }
  659. func (rds *SDBInstance) RecoveryFromBackup(conf *cloudprovider.SDBInstanceRecoveryConfig) error {
  660. if len(conf.OriginDBInstanceExternalId) == 0 {
  661. conf.OriginDBInstanceExternalId = rds.DBInstanceId
  662. }
  663. return rds.region.RecoveryDBInstanceFromBackup(conf.OriginDBInstanceExternalId, rds.DBInstanceId, conf.BackupId, conf.Databases)
  664. }
  665. func (region *SRegion) RecoveryDBInstanceFromBackup(srcId, destId string, backupId string, databases map[string]string) error {
  666. params := map[string]string{
  667. "RegionId": region.RegionId,
  668. "DBInstanceId": srcId,
  669. "TargetDBInstanceId": destId,
  670. "BackupId": backupId,
  671. "DbNames": jsonutils.Marshal(databases).String(),
  672. }
  673. _, err := region.rdsRequest("RecoveryDBInstance", params)
  674. if err != nil {
  675. return errors.Wrap(err, "rdsRequest.RecoveryDBInstance")
  676. }
  677. return nil
  678. }
  679. func (rds *SDBInstance) CreateDatabase(conf *cloudprovider.SDBInstanceDatabaseCreateConfig) error {
  680. return rds.region.CreateDBInstanceDatabae(rds.DBInstanceId, conf.CharacterSet, conf.Name, conf.Description)
  681. }
  682. func (rds *SDBInstance) CreateAccount(conf *cloudprovider.SDBInstanceAccountCreateConfig) error {
  683. return rds.region.CreateDBInstanceAccount(rds.DBInstanceId, conf.Name, conf.Password, conf.Description)
  684. }
  685. func (rds *SDBInstance) Renew(bc billing.SBillingCycle) error {
  686. return rds.region.RenewInstance(rds.DBInstanceId, bc)
  687. }
  688. func (region *SRegion) RenewDBInstance(instanceId string, bc billing.SBillingCycle) error {
  689. params := map[string]string{
  690. "DBInstanceId": instanceId,
  691. "Period": fmt.Sprintf("%d", bc.GetMonths()),
  692. "ClientToken": utils.GenRequestId(20),
  693. }
  694. _, err := region.rdsRequest("RenewInstance", params)
  695. return err
  696. }
  697. func (rds *SDBInstance) GetTags() (map[string]string, error) {
  698. tags, err := rds.region.ListResourceTags("rds", "INSTANCE", []string{rds.GetId()})
  699. if err != nil {
  700. return nil, errors.Wrap(err, "rds.region.ListResourceTags")
  701. }
  702. if _, ok := tags[rds.GetId()]; !ok {
  703. return map[string]string{}, nil
  704. }
  705. return *tags[rds.GetId()], nil
  706. }
  707. func (rds *SDBInstance) SetTags(tags map[string]string, replace bool) error {
  708. return rds.region.SetResourceTags("rds", "INSTANCE", []string{rds.GetId()}, tags, replace)
  709. }
  710. func (rds *SDBInstance) Update(ctx context.Context, input cloudprovider.SDBInstanceUpdateOptions) error {
  711. return rds.region.ModifyDBInstanceName(rds.DBInstanceId, input.NAME)
  712. }
  713. func (region *SRegion) ModifyDBInstanceName(id, name string) error {
  714. params := map[string]string{
  715. "DBInstanceId": id,
  716. "DBInstanceDescription": name,
  717. }
  718. _, err := region.rdsRequest("ModifyDBInstanceDescription", params)
  719. if err != nil {
  720. return errors.Wrap(err, "ModifyDBInstanceDescription")
  721. }
  722. return nil
  723. }