mongodb.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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 qcloud
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. sdkerrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/pkg/utils"
  23. billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
  24. api "yunion.io/x/cloudmux/pkg/apis/compute"
  25. "yunion.io/x/cloudmux/pkg/cloudprovider"
  26. "yunion.io/x/cloudmux/pkg/multicloud"
  27. )
  28. type SMongoDB struct {
  29. QcloudTags
  30. multicloud.SVirtualResourceBase
  31. multicloud.SBillingBase
  32. multicloud.SMongodbBase
  33. region *SRegion
  34. IOPS int
  35. NetworkAddress string
  36. AutoRenewFlag int `json:"AutoRenewFlag"`
  37. CloneInstances []interface{} `json:"CloneInstances"`
  38. ClusterType int `json:"ClusterType"`
  39. ClusterVer int `json:"ClusterVer"`
  40. ConfigServerCpuNum int `json:"ConfigServerCpuNum"`
  41. ConfigServerMemory int `json:"ConfigServerMemory"`
  42. ConfigServerNodeNum int `json:"ConfigServerNodeNum"`
  43. ConfigServerVolume int `json:"ConfigServerVolume"`
  44. CpuNum int `json:"CpuNum"`
  45. CreateTime time.Time `json:"CreateTime"`
  46. DeadLine string `json:"DeadLine"`
  47. InstanceId string `json:"InstanceId"`
  48. InstanceName string `json:"InstanceName"`
  49. InstanceStatusDesc string `json:"InstanceStatusDesc"`
  50. InstanceTaskDesc string `json:"InstanceTaskDesc"`
  51. InstanceTaskId int `json:"InstanceTaskId"`
  52. InstanceType int `json:"InstanceType"`
  53. InstanceVer int `json:"InstanceVer"`
  54. MachineType string `json:"MachineType"`
  55. MaintenanceEnd string `json:"MaintenanceEnd"`
  56. MaintenanceStart string `json:"MaintenanceStart"`
  57. Memory int `json:"Memory"`
  58. MongoVersion string `json:"MongoVersion"`
  59. MongosCpuNum int `json:"MongosCpuNum"`
  60. MongosMemory int `json:"MongosMemory"`
  61. MongosNodeNum int `json:"MongosNodeNum"`
  62. NetType int `json:"NetType"`
  63. PayMode int `json:"PayMode"`
  64. ProjectId int `json:"ProjectId"`
  65. Protocol int `json:"Protocol"`
  66. Readonlyinstances []interface{} `json:"ReadonlyInstances"`
  67. RealInstanceId string `json:"RealInstanceId"`
  68. Region string `json:"Region"`
  69. Relatedinstance struct {
  70. InstanceId string `json:"InstanceId"`
  71. Region string `json:"Region"`
  72. } `json:"RelatedInstance"`
  73. Replicasets []struct {
  74. Memory int `json:"Memory"`
  75. OplogSize int `json:"OplogSize"`
  76. RealReplicasetId string `json:"RealReplicaSetId"`
  77. ReplicaSetId string `json:"ReplicaSetId"`
  78. ReplicaSetName string `json:"ReplicaSetName"`
  79. SecondaryNum int `json:"SecondaryNum"`
  80. UsedVolume int `json:"UsedVolume"`
  81. Volume int `json:"Volume"`
  82. } `json:"ReplicaSets"`
  83. ReplicationSetNum int `json:"ReplicationSetNum"`
  84. SecondaryNum int `json:"SecondaryNum"`
  85. StandbyInstances []interface{} `json:"StandbyInstances"`
  86. Status int `json:"Status"`
  87. SubnetId string `json:"SubnetId"`
  88. UsedVolume int `json:"UsedVolume"`
  89. Vip string `json:"Vip"`
  90. Volume int `json:"Volume"`
  91. VpcId string `json:"VpcId"`
  92. Vport int `json:"Vport"`
  93. Zone string `json:"Zone"`
  94. }
  95. func (self *SMongoDB) GetGlobalId() string {
  96. return self.InstanceId
  97. }
  98. func (self *SMongoDB) GetId() string {
  99. return self.InstanceId
  100. }
  101. func (self *SMongoDB) GetName() string {
  102. return self.InstanceName
  103. }
  104. func (self *SMongoDB) GetStatus() string {
  105. switch self.Status {
  106. case 0:
  107. return api.MONGO_DB_STATUS_CREATING
  108. case 1:
  109. return api.MONGO_DB_STATUS_PROCESSING
  110. case 2:
  111. return api.MONGO_DB_STATUS_RUNNING
  112. case -2, -3:
  113. return api.MONGO_DB_STATUS_DELETING
  114. }
  115. return fmt.Sprintf("%d", self.Status)
  116. }
  117. func (self *SMongoDB) Refresh() error {
  118. ins, err := self.region.GetMongoDB(self.InstanceId)
  119. if err != nil {
  120. return errors.Wrapf(err, "GetMongoDB")
  121. }
  122. return jsonutils.Update(self, ins)
  123. }
  124. func (self *SMongoDB) GetProjectId() string {
  125. return fmt.Sprintf("%d", self.ProjectId)
  126. }
  127. func (self *SMongoDB) GetVpcId() string {
  128. return self.VpcId
  129. }
  130. func (self *SMongoDB) GetNetworkId() string {
  131. return self.SubnetId
  132. }
  133. func (self *SMongoDB) GetCreatedAt() time.Time {
  134. return self.CreateTime.Add(time.Hour * -8)
  135. }
  136. func (self *SMongoDB) GetExpiredAt() time.Time {
  137. return time.Time{}
  138. }
  139. func (self *SMongoDB) GetIpAddr() string {
  140. return self.Vip
  141. }
  142. func (self *SMongoDB) GetVcpuCount() int {
  143. return self.CpuNum
  144. }
  145. func (self *SMongoDB) GetVmemSizeMb() int {
  146. return self.Memory
  147. }
  148. func (self *SMongoDB) GetReplicationNum() int {
  149. switch self.GetCategory() {
  150. case api.MONGO_DB_CATEGORY_SHARDING:
  151. return self.ReplicationSetNum
  152. case api.MONGO_DB_CATEGORY_REPLICATE:
  153. return 3
  154. }
  155. return self.ReplicationSetNum
  156. }
  157. func (self *SMongoDB) GetDiskSizeMb() int {
  158. return self.Volume
  159. }
  160. func (self *SMongoDB) GetZoneId() string {
  161. return self.Zone
  162. }
  163. func (self *SMongoDB) GetBillingType() string {
  164. // 计费模式:0-按量计费,1-包年包月
  165. if self.PayMode == 1 {
  166. return billing_api.BILLING_TYPE_PREPAID
  167. } else {
  168. return billing_api.BILLING_TYPE_POSTPAID
  169. }
  170. }
  171. func (self *SMongoDB) IsAutoRenew() bool {
  172. return self.AutoRenewFlag == 1
  173. }
  174. func (self *SMongoDB) GetCategory() string {
  175. switch self.ClusterType {
  176. case 0:
  177. return api.MONGO_DB_CATEGORY_REPLICATE
  178. case 1:
  179. return api.MONGO_DB_CATEGORY_SHARDING
  180. default:
  181. return fmt.Sprintf("%d", self.ClusterType)
  182. }
  183. }
  184. func (self *SMongoDB) GetEngine() string {
  185. if utils.IsInStringArray("WT", strings.Split(self.MongoVersion, "_")) {
  186. return api.MONGO_DB_ENGINE_WIRED_TIGER
  187. }
  188. return api.MONGO_DB_ENGINE_ROCKS
  189. }
  190. func (self *SMongoDB) GetEngineVersion() string {
  191. vers := strings.Split(self.MongoVersion, "_")
  192. if len(vers) > 1 {
  193. return strings.Join(strings.Split(vers[1], ""), ".")
  194. }
  195. return ""
  196. }
  197. func (self *SMongoDB) GetInstanceType() string {
  198. return self.MachineType
  199. }
  200. func (self *SMongoDB) GetMaintainTime() string {
  201. return fmt.Sprintf("%s-%s", self.MaintenanceStart, self.MaintenanceEnd)
  202. }
  203. func (self *SMongoDB) GetPort() int {
  204. return self.Vport
  205. }
  206. func (self *SMongoDB) Delete() error {
  207. return self.region.DeleteMongoDB(self.InstanceId)
  208. }
  209. func (self *SRegion) DeleteMongoDB(id string) error {
  210. err := self.IsolateMongoDB(id)
  211. if err != nil {
  212. return errors.Wrapf(err, "IsolateDBInstance")
  213. }
  214. return cloudprovider.Wait(time.Second*10, time.Minute*3, func() (bool, error) {
  215. err = self.OfflineIsolatedMongoDB(id)
  216. if err == nil {
  217. return true, nil
  218. }
  219. if e, ok := errors.Cause(err).(*sdkerrors.TencentCloudSDKError); ok && e.Code == "InvalidParameterValue.LockFailed" {
  220. return false, nil
  221. }
  222. return true, err
  223. })
  224. }
  225. func (self *SMongoDB) SetTags(tags map[string]string, replace bool) error {
  226. return self.region.SetResourceTags("mongodb", "instance", []string{self.InstanceId}, tags, replace)
  227. }
  228. func (self *SMongoDB) GetIBackups() ([]cloudprovider.SMongoDBBackup, error) {
  229. return self.region.GetMongoDBBackups(self.InstanceId)
  230. }
  231. func (self *SRegion) IsolateMongoDB(id string) error {
  232. params := map[string]string{
  233. "InstanceId": id,
  234. }
  235. _, err := self.mongodbRequest("IsolateDBInstance", params)
  236. return errors.Wrapf(err, "IsolateDBInstance")
  237. }
  238. func (self *SRegion) OfflineIsolatedMongoDB(id string) error {
  239. params := map[string]string{
  240. "InstanceId": id,
  241. }
  242. _, err := self.mongodbRequest("OfflineIsolatedDBInstance", params)
  243. return errors.Wrapf(err, "OfflineIsolatedDBInstance")
  244. }
  245. func (self *SRegion) GetMongoDBs(ids []string, limit, offset int) ([]SMongoDB, int, error) {
  246. if limit < 1 || limit > 100 {
  247. limit = 100
  248. }
  249. params := map[string]string{
  250. "Limit": fmt.Sprintf("%d", limit),
  251. "Offset": fmt.Sprintf("%d", offset),
  252. }
  253. for i, id := range ids {
  254. params[fmt.Sprintf("InstanceIds.%d", i)] = id
  255. }
  256. resp, err := self.mongodbRequest("DescribeDBInstances", params)
  257. if err != nil {
  258. return nil, 0, errors.Wrapf(err, "DescribeDBInstances")
  259. }
  260. dbs := []SMongoDB{}
  261. err = resp.Unmarshal(&dbs, "InstanceDetails")
  262. if err != nil {
  263. return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
  264. }
  265. totalCount, _ := resp.Float("TotalCount")
  266. return dbs, int(totalCount), nil
  267. }
  268. func (self *SMongoDB) GetIops() int {
  269. return self.IOPS
  270. }
  271. func (self *SMongoDB) GetNetworkAddress() string {
  272. return self.NetworkAddress
  273. }
  274. func (self *SRegion) GetICloudMongoDBs() ([]cloudprovider.ICloudMongoDB, error) {
  275. dbs := []SMongoDB{}
  276. for {
  277. part, total, err := self.GetMongoDBs(nil, 100, len(dbs))
  278. if err != nil {
  279. return nil, errors.Wrapf(err, "GetMongoDBs")
  280. }
  281. dbs = append(dbs, part...)
  282. if len(dbs) >= total {
  283. break
  284. }
  285. }
  286. ret := []cloudprovider.ICloudMongoDB{}
  287. for i := range dbs {
  288. dbs[i].region = self
  289. ret = append(ret, &dbs[i])
  290. }
  291. return ret, nil
  292. }
  293. func (self *SRegion) GetMongoDBBackups(id string) ([]cloudprovider.SMongoDBBackup, error) {
  294. params := map[string]string{
  295. "BackupMethod": "2",
  296. "InstanceId": id,
  297. }
  298. resp, err := self.mongodbRequest("DescribeDBBackups", params)
  299. if err != nil {
  300. return nil, errors.Wrapf(err, "DescribeDBBackups")
  301. }
  302. backups := []struct {
  303. InstanceId string
  304. BackupType int
  305. BackupName string
  306. BackupDesc string
  307. BackupSize int
  308. StartTime time.Time
  309. EndTime time.Time
  310. Status int
  311. BackupMethod int
  312. }{}
  313. err = resp.Unmarshal(&backups, "BackupList")
  314. if err != nil {
  315. return nil, errors.Wrapf(err, "resp.Unmarshal")
  316. }
  317. ret := []cloudprovider.SMongoDBBackup{}
  318. for _, backup := range backups {
  319. b := cloudprovider.SMongoDBBackup{
  320. Name: backup.BackupName,
  321. Description: backup.BackupDesc,
  322. BackupSizeKb: backup.BackupSize,
  323. }
  324. b.StartTime = backup.StartTime.Add(time.Hour * -8)
  325. b.EndTime = backup.EndTime.Add(time.Hour * -8)
  326. switch backup.Status {
  327. case 1:
  328. b.Status = cloudprovider.MongoDBBackupStatusCreating
  329. case 2:
  330. b.Status = cloudprovider.MongoDBBackupStatusAvailable
  331. default:
  332. b.Status = cloudprovider.MongoDBBackupStatusUnknown
  333. }
  334. b.BackupMethod = cloudprovider.MongoDBBackupMethodLogical
  335. if backup.BackupMethod == 0 {
  336. b.BackupMethod = cloudprovider.MongoDBBackupMethodPhysical
  337. }
  338. b.BackupType = cloudprovider.MongoDBBackupTypeAuto
  339. if backup.BackupType == 1 {
  340. b.BackupType = cloudprovider.MongoDBBackupTypeManual
  341. }
  342. ret = append(ret, b)
  343. }
  344. return ret, nil
  345. }
  346. func (self *SRegion) GetMongoDB(id string) (*SMongoDB, error) {
  347. dbs, _, err := self.GetMongoDBs([]string{id}, 1, 0)
  348. if err != nil {
  349. return nil, errors.Wrapf(err, "GetMongoDB(%s)", id)
  350. }
  351. for i := range dbs {
  352. dbs[i].region = self
  353. return &dbs[i], nil
  354. }
  355. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  356. }
  357. func (self *SRegion) GetICloudMongoDBById(id string) (cloudprovider.ICloudMongoDB, error) {
  358. db, err := self.GetMongoDB(id)
  359. if err != nil {
  360. return nil, errors.Wrapf(err, "GetMongoDB")
  361. }
  362. return db, nil
  363. }