dbinstance.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  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 aliyun
  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. netInfo []SDBInstanceNetwork
  42. region *SRegion
  43. AccountMaxQuantity int
  44. AccountType string
  45. CanTempUpgrade bool
  46. Category string
  47. AvailabilityValue string
  48. DBInstanceDescription string
  49. DBInstanceId string
  50. ConnectionMode string
  51. ConnectionString string
  52. ConnectionDomain 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. ResourceGroupId string
  85. VSwitchId string
  86. VpcCloudInstanceId string
  87. VpcId string
  88. ZoneId string
  89. Extra SDBInstanceExtra
  90. SecurityIPList string
  91. SecurityIPMode string
  92. SupportCreateSuperAccount string
  93. SupportUpgradeAccountType string
  94. TempUpgradeTimeEnd time.Time
  95. TempUpgradeTimeStart time.Time
  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) GetExpiredAt() time.Time {
  153. return rds.ExpireTime
  154. }
  155. func (rds *SDBInstance) GetCreatedAt() time.Time {
  156. return rds.CreateTime
  157. }
  158. func (rds *SDBInstance) GetStorageType() string {
  159. return rds.DBInstanceStorageType
  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) GetIOPS() int {
  260. if rds.MaxIOPS == 0 {
  261. rds.Refresh()
  262. }
  263. return rds.MaxIOPS
  264. }
  265. func (rds *SDBInstance) GetNetworkAddress() string {
  266. return rds.ConnectionDomain
  267. }
  268. func (rds *SDBInstance) getZone(index int) string {
  269. zoneStr := strings.Replace(rds.ZoneId, ")", "", -1)
  270. zoneInfo := strings.Split(zoneStr, ",")
  271. if len(zoneInfo) < index {
  272. return ""
  273. }
  274. zone := zoneInfo[index-1]
  275. zoneCode := zone[len(zone)-1]
  276. if strings.HasPrefix(rds.ZoneId, fmt.Sprintf("%s-", rds.RegionId)) {
  277. return fmt.Sprintf("%s-%s", rds.RegionId, string(zoneCode))
  278. }
  279. return fmt.Sprintf("%s%s", rds.RegionId, string(zoneCode))
  280. }
  281. func (rds *SDBInstance) GetDBNetworks() ([]cloudprovider.SDBInstanceNetwork, error) {
  282. netInfo, err := rds.region.GetDBInstanceNetInfo(rds.DBInstanceId)
  283. if err != nil {
  284. return nil, errors.Wrapf(err, "GetDBInstanceNetInfo")
  285. }
  286. networks := []cloudprovider.SDBInstanceNetwork{}
  287. for _, net := range netInfo {
  288. if net.IPType == "Private" {
  289. network := cloudprovider.SDBInstanceNetwork{}
  290. network.IP = net.IPAddress
  291. network.NetworkId = net.VSwitchId
  292. networks = append(networks, network)
  293. }
  294. }
  295. return networks, nil
  296. }
  297. func (rds *SDBInstance) fetchNetInfo() error {
  298. if len(rds.netInfo) > 0 {
  299. return nil
  300. }
  301. netInfo, err := rds.region.GetDBInstanceNetInfo(rds.DBInstanceId)
  302. if err != nil {
  303. return errors.Wrap(err, "GetDBInstanceNetInfo")
  304. }
  305. rds.netInfo = netInfo
  306. return nil
  307. }
  308. func (rds *SDBInstance) GetInternalConnectionStr() string {
  309. err := rds.fetchNetInfo()
  310. if err != nil {
  311. log.Errorf("failed to fetch netInfo error: %v", err)
  312. return ""
  313. }
  314. str := ""
  315. for _, net := range rds.netInfo {
  316. if net.IPType != "Public" {
  317. if net.IPType == "Private" {
  318. return net.ConnectionString
  319. } else if net.IPType == "Inner" {
  320. str = net.ConnectionString
  321. }
  322. }
  323. }
  324. return str
  325. }
  326. func (rds *SDBInstance) GetConnectionStr() string {
  327. err := rds.fetchNetInfo()
  328. if err != nil {
  329. log.Errorf("failed to fetch netInfo error: %v", err)
  330. return ""
  331. }
  332. for _, net := range rds.netInfo {
  333. if net.IPType == "Public" {
  334. return net.ConnectionString
  335. }
  336. }
  337. return ""
  338. }
  339. func (region *SRegion) GetDBInstances(ids []string, offset int, limit int) ([]SDBInstance, int, error) {
  340. if limit > 50 || limit <= 0 {
  341. limit = 50
  342. }
  343. params := make(map[string]string)
  344. params["RegionId"] = region.RegionId
  345. params["PageSize"] = fmt.Sprintf("%d", limit)
  346. params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
  347. body, err := region.rdsRequest("DescribeDBInstances", params)
  348. if err != nil {
  349. return nil, 0, errors.Wrapf(err, "GetDBInstances")
  350. }
  351. instances := []SDBInstance{}
  352. err = body.Unmarshal(&instances, "Items", "DBInstance")
  353. if err != nil {
  354. return nil, 0, errors.Wrapf(err, "GetDBInstances.Unmarshal")
  355. }
  356. total, _ := body.Int("TotalRecordCount")
  357. return instances, int(total), nil
  358. }
  359. func (region *SRegion) GetIDBInstanceById(instanceId string) (cloudprovider.ICloudDBInstance, error) {
  360. rds, err := region.GetDBInstanceDetail(instanceId)
  361. if err != nil {
  362. return nil, err
  363. }
  364. rds.region = region
  365. return rds, nil
  366. }
  367. func (region *SRegion) GetIDBInstances() ([]cloudprovider.ICloudDBInstance, error) {
  368. instances := []SDBInstance{}
  369. for {
  370. part, total, err := region.GetDBInstances([]string{}, len(instances), 50)
  371. if err != nil {
  372. return nil, err
  373. }
  374. instances = append(instances, part...)
  375. if len(instances) >= total {
  376. break
  377. }
  378. }
  379. idbinstances := []cloudprovider.ICloudDBInstance{}
  380. for i := 0; i < len(instances); i++ {
  381. instances[i].region = region
  382. idbinstances = append(idbinstances, &instances[i])
  383. }
  384. return idbinstances, nil
  385. }
  386. func (region *SRegion) GetDBInstanceDetail(instanceId string) (*SDBInstance, error) {
  387. if len(instanceId) == 0 {
  388. return nil, cloudprovider.ErrNotFound
  389. }
  390. params := map[string]string{}
  391. params["RegionId"] = region.RegionId
  392. params["DBInstanceId"] = instanceId
  393. body, err := region.rdsRequest("DescribeDBInstanceAttribute", params)
  394. if err != nil {
  395. return nil, errors.Wrapf(err, "GetDBInstanceDetail")
  396. }
  397. instances := []SDBInstance{}
  398. err = body.Unmarshal(&instances, "Items", "DBInstanceAttribute")
  399. if err != nil {
  400. return nil, errors.Wrapf(err, "GetDBInstanceDetail.Unmarshal")
  401. }
  402. if len(instances) == 1 {
  403. instances[0].region = region
  404. return &instances[0], nil
  405. }
  406. if len(instances) == 0 {
  407. return nil, cloudprovider.ErrNotFound
  408. }
  409. return nil, cloudprovider.ErrDuplicateId
  410. }
  411. func (region *SRegion) DeleteDBInstance(instanceId string) error {
  412. params := map[string]string{}
  413. params["RegionId"] = region.RegionId
  414. params["DBInstanceId"] = instanceId
  415. _, err := region.rdsRequest("DeleteDBInstance", params)
  416. return err
  417. }
  418. type SDBInstanceWeight struct {
  419. }
  420. type SDBInstanceWeights struct {
  421. DBInstanceWeight []SDBInstanceWeight
  422. }
  423. type SsecurityIPGroup struct {
  424. }
  425. type SSecurityIPGroups struct {
  426. securityIPGroup []SsecurityIPGroup
  427. }
  428. type SDBInstanceNetwork struct {
  429. ConnectionString string
  430. ConnectionStringType string
  431. DBInstanceWeights SDBInstanceWeights
  432. IPAddress string
  433. IPType string
  434. Port int
  435. SecurityIPGroups SSecurityIPGroups
  436. Upgradeable string
  437. VPCId string
  438. VSwitchId string
  439. }
  440. func (network *SDBInstanceNetwork) GetGlobalId() string {
  441. return network.IPAddress
  442. }
  443. func (network *SDBInstanceNetwork) GetINetworkId() string {
  444. return network.VSwitchId
  445. }
  446. func (network *SDBInstanceNetwork) GetIP() string {
  447. return network.IPAddress
  448. }
  449. func (region *SRegion) GetDBInstanceNetInfo(instanceId string) ([]SDBInstanceNetwork, error) {
  450. params := map[string]string{}
  451. params["RegionId"] = region.RegionId
  452. params["DBInstanceId"] = instanceId
  453. body, err := region.rdsRequest("DescribeDBInstanceNetInfo", params)
  454. if err != nil {
  455. return nil, errors.Wrapf(err, "GetDBInstanceNetwork")
  456. }
  457. networks := []SDBInstanceNetwork{}
  458. err = body.Unmarshal(&networks, "DBInstanceNetInfos", "DBInstanceNetInfo")
  459. if err != nil {
  460. return nil, err
  461. }
  462. return networks, nil
  463. }
  464. func (rds *SDBInstance) GetIDBInstanceParameters() ([]cloudprovider.ICloudDBInstanceParameter, error) {
  465. parameters, err := rds.region.GetDBInstanceParameters(rds.DBInstanceId)
  466. if err != nil {
  467. return nil, err
  468. }
  469. iparameters := []cloudprovider.ICloudDBInstanceParameter{}
  470. for i := 0; i < len(parameters); i++ {
  471. iparameters = append(iparameters, &parameters[i])
  472. }
  473. return iparameters, nil
  474. }
  475. func (self *SDBInstance) GetSecurityGroupIds() ([]string, error) {
  476. return self.region.GetRdsSecgroupIds(self.DBInstanceId)
  477. }
  478. func (self *SDBInstance) SetSecurityGroups(ids []string) error {
  479. return self.region.SetRdsSecgroups(self.DBInstanceId, ids)
  480. }
  481. func (self *SRegion) SetRdsSecgroups(rdsId string, secIds []string) error {
  482. params := map[string]string{
  483. "DBInstanceId": rdsId,
  484. "SecurityGroupId": strings.Join(secIds, ","),
  485. }
  486. _, err := self.rdsRequest("ModifySecurityGroupConfiguration", params)
  487. if err != nil {
  488. return errors.Wrapf(err, "ModifySecurityGroupConfiguration")
  489. }
  490. return nil
  491. }
  492. func (self *SRegion) GetRdsSecgroupIds(rdsId string) ([]string, error) {
  493. params := map[string]string{
  494. "DBInstanceId": rdsId,
  495. }
  496. resp, err := self.rdsRequest("DescribeSecurityGroupConfiguration", params)
  497. if err != nil {
  498. return nil, errors.Wrapf(err, "DescribeSecurityGroupConfiguration")
  499. }
  500. items := []struct {
  501. NetworkType string
  502. SecurityGroupId string
  503. RegionId string
  504. }{}
  505. err = resp.Unmarshal(&items, "Items", "EcsSecurityGroupRelation")
  506. if err != nil {
  507. return nil, errors.Wrapf(err, "resp.Unmarshal")
  508. }
  509. ids := []string{}
  510. for _, item := range items {
  511. ids = append(ids, item.SecurityGroupId)
  512. }
  513. return ids, nil
  514. }
  515. func (rds *SDBInstance) Reboot() error {
  516. return rds.region.RebootDBInstance(rds.DBInstanceId)
  517. }
  518. func (rds *SDBInstance) Delete() error {
  519. return rds.region.DeleteDBInstance(rds.DBInstanceId)
  520. }
  521. func (region *SRegion) RebootDBInstance(instanceId string) error {
  522. params := map[string]string{}
  523. params["RegionId"] = region.RegionId
  524. params["DBInstanceId"] = instanceId
  525. _, err := region.rdsRequest("RestartDBInstance", params)
  526. return err
  527. }
  528. func (rds *SDBInstance) GetIDBInstanceDatabases() ([]cloudprovider.ICloudDBInstanceDatabase, error) {
  529. databases := []SDBInstanceDatabase{}
  530. for {
  531. parts, total, err := rds.region.GetDBInstanceDatabases(rds.DBInstanceId, "", len(databases), 500)
  532. if err != nil {
  533. return nil, err
  534. }
  535. databases = append(databases, parts...)
  536. if len(databases) >= total {
  537. break
  538. }
  539. }
  540. idatabase := []cloudprovider.ICloudDBInstanceDatabase{}
  541. for i := 0; i < len(databases); i++ {
  542. databases[i].instance = rds
  543. idatabase = append(idatabase, &databases[i])
  544. }
  545. return idatabase, nil
  546. }
  547. func (rds *SDBInstance) GetIDBInstanceAccounts() ([]cloudprovider.ICloudDBInstanceAccount, error) {
  548. accounts := []SDBInstanceAccount{}
  549. for {
  550. parts, total, err := rds.region.GetDBInstanceAccounts(rds.DBInstanceId, len(accounts), 50)
  551. if err != nil {
  552. return nil, err
  553. }
  554. accounts = append(accounts, parts...)
  555. if len(accounts) >= total {
  556. break
  557. }
  558. }
  559. iaccounts := []cloudprovider.ICloudDBInstanceAccount{}
  560. for i := 0; i < len(accounts); i++ {
  561. accounts[i].instance = rds
  562. iaccounts = append(iaccounts, &accounts[i])
  563. }
  564. return iaccounts, nil
  565. }
  566. func (rds *SDBInstance) ChangeConfig(cxt context.Context, desc *cloudprovider.SManagedDBInstanceChangeConfig) error {
  567. return rds.region.ChangeDBInstanceConfig(rds.DBInstanceId, string(rds.PayType), desc)
  568. }
  569. func (region *SRegion) ChangeDBInstanceConfig(instanceId, payType string, desc *cloudprovider.SManagedDBInstanceChangeConfig) error {
  570. params := map[string]string{
  571. "RegionId": region.RegionId,
  572. "DBInstanceId": instanceId,
  573. "PayType": payType,
  574. }
  575. if len(desc.InstanceType) > 0 {
  576. params["DBInstanceClass"] = desc.InstanceType
  577. }
  578. if desc.DiskSizeGB > 0 {
  579. params["DBInstanceStorage"] = fmt.Sprintf("%d", desc.DiskSizeGB)
  580. }
  581. _, err := region.rdsRequest("ModifyDBInstanceSpec", params)
  582. if err != nil {
  583. return errors.Wrap(err, "region.rdsRequest.ModifyDBInstanceSpec")
  584. }
  585. return nil
  586. }
  587. func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceCreateConfig) (cloudprovider.ICloudDBInstance, error) {
  588. params := map[string]string{
  589. "RegionId": region.RegionId,
  590. "Engine": desc.Engine,
  591. "EngineVersion": desc.EngineVersion,
  592. "DBInstanceStorage": fmt.Sprintf("%d", desc.DiskSizeGB),
  593. "DBInstanceNetType": "Intranet",
  594. "PayType": "Postpaid",
  595. "SecurityIPList": "0.0.0.0/0",
  596. "DBInstanceDescription": desc.Name,
  597. "InstanceNetworkType": "VPC",
  598. "VPCId": desc.VpcId,
  599. "VSwitchId": desc.NetworkId,
  600. "DBInstanceStorageType": desc.StorageType,
  601. "DBInstanceClass": desc.InstanceType,
  602. "ZoneId": desc.ZoneId,
  603. "ClientToken": utils.GenRequestId(20),
  604. }
  605. switch desc.Category {
  606. case api.ALIYUN_DBINSTANCE_CATEGORY_HA:
  607. params["Category"] = "HighAvailability"
  608. case api.ALIYUN_DBINSTANCE_CATEGORY_BASIC:
  609. params["Category"] = "Basic"
  610. case api.ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON:
  611. params["Category"] = "AlwaysOn"
  612. case api.ALIYUN_DBINSTANCE_CATEGORY_FINANCE:
  613. params["Category"] = "Finance"
  614. }
  615. if len(desc.Address) > 0 {
  616. params["PrivateIpAddress"] = desc.Address
  617. }
  618. if len(desc.ProjectId) > 0 {
  619. params["ResourceGroupId"] = desc.ProjectId
  620. }
  621. if desc.BillingCycle != nil {
  622. params["PayType"] = "Prepaid"
  623. if desc.BillingCycle.GetYears() > 0 {
  624. params["Period"] = "Year"
  625. params["UsedTime"] = fmt.Sprintf("%d", desc.BillingCycle.GetYears())
  626. } else {
  627. params["Period"] = "Month"
  628. params["UsedTime"] = fmt.Sprintf("%d", desc.BillingCycle.GetMonths())
  629. }
  630. params["AutoRenew"] = "False"
  631. if desc.BillingCycle.AutoRenew {
  632. params["AutoRenew"] = "True"
  633. }
  634. }
  635. action := "CreateDBInstance"
  636. if len(desc.MasterInstanceId) > 0 {
  637. action = "CreateReadOnlyDBInstance"
  638. params["DBInstanceId"] = desc.MasterInstanceId
  639. }
  640. resp, err := region.rdsRequest(action, params)
  641. if err != nil {
  642. return nil, errors.Wrapf(err, "rdsRequest")
  643. }
  644. instanceId, err := resp.GetString("DBInstanceId")
  645. if err != nil {
  646. return nil, errors.Wrap(err, `resp.GetString("DBInstanceId")`)
  647. }
  648. region.SetResourceTags(ALIYUN_SERVICE_RDS, "INSTANCE", instanceId, desc.Tags, false)
  649. return region.GetIDBInstanceById(instanceId)
  650. }
  651. func (rds *SDBInstance) GetMasterInstanceId() string {
  652. if len(rds.MasterInstanceId) > 0 {
  653. return rds.MasterInstanceId
  654. }
  655. rds.Refresh()
  656. return rds.MasterInstanceId
  657. }
  658. func (region *SRegion) OpenPublicConnection(instanceId string) error {
  659. rds, err := region.GetDBInstanceDetail(instanceId)
  660. if err != nil {
  661. return err
  662. }
  663. params := map[string]string{
  664. "RegionId": region.RegionId,
  665. "ConnectionStringPrefix": rds.DBInstanceId + rand.String(3),
  666. "DBInstanceId": rds.DBInstanceId,
  667. "Port": fmt.Sprintf("%d", rds.Port),
  668. }
  669. _, err = rds.region.rdsRequest("AllocateInstancePublicConnection", params)
  670. if err != nil {
  671. return errors.Wrap(err, "rdsRequest(AllocateInstancePublicConnection)")
  672. }
  673. return nil
  674. }
  675. func (rds *SDBInstance) OpenPublicConnection() error {
  676. if url := rds.GetConnectionStr(); len(url) == 0 {
  677. err := rds.region.OpenPublicConnection(rds.DBInstanceId)
  678. if err != nil {
  679. return err
  680. }
  681. rds.netInfo = []SDBInstanceNetwork{}
  682. }
  683. return nil
  684. }
  685. func (region *SRegion) ClosePublicConnection(instanceId string) error {
  686. netInfo, err := region.GetDBInstanceNetInfo(instanceId)
  687. if err != nil {
  688. return errors.Wrap(err, "GetDBInstanceNetInfo")
  689. }
  690. for _, net := range netInfo {
  691. if net.IPType == "Public" {
  692. params := map[string]string{
  693. "RegionId": region.RegionId,
  694. "CurrentConnectionString": net.ConnectionString,
  695. "DBInstanceId": instanceId,
  696. }
  697. _, err = region.rdsRequest("ReleaseInstancePublicConnection", params)
  698. if err != nil {
  699. return errors.Wrap(err, "rdsRequest(ReleaseInstancePublicConnection)")
  700. }
  701. }
  702. }
  703. return nil
  704. }
  705. func (rds *SDBInstance) ClosePublicConnection() error {
  706. return rds.region.ClosePublicConnection(rds.DBInstanceId)
  707. }
  708. func (rds *SDBInstance) RecoveryFromBackup(conf *cloudprovider.SDBInstanceRecoveryConfig) error {
  709. if len(conf.OriginDBInstanceExternalId) == 0 {
  710. conf.OriginDBInstanceExternalId = rds.DBInstanceId
  711. }
  712. return rds.region.RecoveryDBInstanceFromBackup(conf.OriginDBInstanceExternalId, rds.DBInstanceId, conf.BackupId, conf.Databases)
  713. }
  714. func (region *SRegion) RecoveryDBInstanceFromBackup(srcId, destId string, backupId string, databases map[string]string) error {
  715. params := map[string]string{
  716. "RegionId": region.RegionId,
  717. "DBInstanceId": srcId,
  718. "TargetDBInstanceId": destId,
  719. "BackupId": backupId,
  720. "DbNames": jsonutils.Marshal(databases).String(),
  721. }
  722. _, err := region.rdsRequest("RecoveryDBInstance", params)
  723. if err != nil {
  724. return errors.Wrap(err, "rdsRequest.RecoveryDBInstance")
  725. }
  726. return nil
  727. }
  728. func (rds *SDBInstance) GetProjectId() string {
  729. return rds.ResourceGroupId
  730. }
  731. func (rds *SDBInstance) CreateDatabase(conf *cloudprovider.SDBInstanceDatabaseCreateConfig) error {
  732. return rds.region.CreateDBInstanceDatabae(rds.DBInstanceId, conf.CharacterSet, conf.Name, conf.Description)
  733. }
  734. func (rds *SDBInstance) CreateAccount(conf *cloudprovider.SDBInstanceAccountCreateConfig) error {
  735. return rds.region.CreateDBInstanceAccount(rds.DBInstanceId, conf.Name, conf.Password, conf.Description)
  736. }
  737. func (rds *SDBInstance) Renew(bc billing.SBillingCycle) error {
  738. return rds.region.RenewInstance(rds.DBInstanceId, bc)
  739. }
  740. func (rds *SDBInstance) SetAutoRenew(bc billing.SBillingCycle) error {
  741. month := 1
  742. if bc.GetMonths() > 0 {
  743. month = bc.GetMonths()
  744. }
  745. return rds.region.ModifyInstanceAutoRenewalAttribute(rds.DBInstanceId, month, bc.AutoRenew)
  746. }
  747. func (region *SRegion) ModifyInstanceAutoRenewalAttribute(rdsId string, month int, autoRenew bool) error {
  748. params := map[string]string{
  749. "RegionId": region.RegionId,
  750. "DBInstanceId": rdsId,
  751. "AutoRenew": "False",
  752. "ClientToken": utils.GenRequestId(20),
  753. }
  754. if autoRenew {
  755. params["AutoRenew"] = "True"
  756. params["Duration"] = fmt.Sprintf("%d", month)
  757. }
  758. _, err := region.rdsRequest("ModifyInstanceAutoRenewalAttribute", params)
  759. if err != nil {
  760. return errors.Wrap(err, "ModifyInstanceAutoRenewalAttribute")
  761. }
  762. return nil
  763. }
  764. func (rds *SDBInstance) Update(ctx context.Context, input cloudprovider.SDBInstanceUpdateOptions) error {
  765. return rds.region.ModifyDBInstanceName(rds.DBInstanceId, input.NAME)
  766. }
  767. func (region *SRegion) ModifyDBInstanceName(id, name string) error {
  768. params := map[string]string{
  769. "DBInstanceId": id,
  770. "DBInstanceDescription": name,
  771. }
  772. _, err := region.rdsRequest("ModifyDBInstanceDescription", params)
  773. if err != nil {
  774. return errors.Wrap(err, "ModifyDBInstanceDescription")
  775. }
  776. return nil
  777. }
  778. func (region *SRegion) RenewDBInstance(instanceId string, bc billing.SBillingCycle) error {
  779. params := map[string]string{
  780. "DBInstanceId": instanceId,
  781. "Period": fmt.Sprintf("%d", bc.GetMonths()),
  782. "ClientToken": utils.GenRequestId(20),
  783. }
  784. _, err := region.rdsRequest("RenewInstance", params)
  785. return err
  786. }
  787. func (self *SDBInstance) GetTags() (map[string]string, error) {
  788. _, tags, err := self.region.ListSysAndUserTags(ALIYUN_SERVICE_RDS, "INSTANCE", self.DBInstanceId)
  789. if err != nil {
  790. return nil, errors.Wrapf(err, "ListTags")
  791. }
  792. tagMaps := map[string]string{}
  793. for k, v := range tags {
  794. tagMaps[strings.ToLower(k)] = v
  795. }
  796. return tagMaps, nil
  797. }
  798. func (self *SDBInstance) GetSysTags() map[string]string {
  799. tags, _, err := self.region.ListSysAndUserTags(ALIYUN_SERVICE_RDS, "INSTANCE", self.DBInstanceId)
  800. if err != nil {
  801. return nil
  802. }
  803. tagMaps := map[string]string{}
  804. for k, v := range tags {
  805. tagMaps[strings.ToLower(k)] = v
  806. }
  807. return tagMaps
  808. }
  809. func (rds *SDBInstance) SetTags(tags map[string]string, replace bool) error {
  810. return rds.region.SetResourceTags(ALIYUN_SERVICE_RDS, "INSTANCE", rds.GetId(), tags, replace)
  811. }