cloudprovider_quotas.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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 models
  15. import (
  16. "context"
  17. "fmt"
  18. "yunion.io/x/cloudmux/pkg/cloudprovider"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/util/compare"
  22. "yunion.io/x/sqlchemy"
  23. api "yunion.io/x/onecloud/pkg/apis/compute"
  24. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  25. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  26. "yunion.io/x/onecloud/pkg/httperrors"
  27. "yunion.io/x/onecloud/pkg/mcclient"
  28. "yunion.io/x/onecloud/pkg/util/stringutils2"
  29. )
  30. // +onecloud:swagger-gen-ignore
  31. type SCloudproviderQuotaManager struct {
  32. db.SStandaloneResourceBaseManager
  33. db.SExternalizedResourceBaseManager
  34. SManagedResourceBaseManager
  35. SCloudregionResourceBaseManager
  36. }
  37. var CloudproviderQuotaManager *SCloudproviderQuotaManager
  38. func init() {
  39. CloudproviderQuotaManager = &SCloudproviderQuotaManager{
  40. SStandaloneResourceBaseManager: db.NewStandaloneResourceBaseManager(
  41. SCloudproviderQuota{},
  42. "cloudprovider_quotas_tbl",
  43. "cloudproviderquota",
  44. "cloudproviderquotas",
  45. ),
  46. }
  47. CloudproviderQuotaManager.SetVirtualObject(CloudproviderQuotaManager)
  48. }
  49. // +onecloud:swagger-gen-ignore
  50. type SCloudproviderQuota struct {
  51. db.SStandaloneResourceBase
  52. db.SExternalizedResourceBase
  53. SManagedResourceBase
  54. SCloudregionResourceBase
  55. // 配额范围
  56. // cloudregion: 区域级别
  57. // cloudprovider: 云订阅级别
  58. QuotaRange string `width:"32" charset:"ascii" list:"user"`
  59. // 已使用的配额
  60. // -1代表未从云平台拿到已使用配额信息
  61. UsedCount int64 `nullable:"false" default:"0" list:"user"`
  62. // 最大配额限制
  63. MaxCount int64 `nullable:"false" default:"0" list:"user"`
  64. // 配额类型
  65. QuotaType string `width:"64" charset:"ascii" list:"user"`
  66. }
  67. func (manager *SCloudproviderQuotaManager) GetContextManagers() [][]db.IModelManager {
  68. return [][]db.IModelManager{
  69. {CloudproviderManager},
  70. }
  71. }
  72. func (man *SCloudproviderQuotaManager) ListItemFilter(
  73. ctx context.Context,
  74. q *sqlchemy.SQuery,
  75. userCred mcclient.TokenCredential,
  76. query api.CloudproviderQuotaListInput,
  77. ) (*sqlchemy.SQuery, error) {
  78. var err error
  79. q, err = man.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StandaloneResourceListInput)
  80. if err != nil {
  81. return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.ListItemFilter")
  82. }
  83. q, err = man.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  84. if err != nil {
  85. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  86. }
  87. q, err = man.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
  88. if err != nil {
  89. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
  90. }
  91. q, err = man.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
  92. if err != nil {
  93. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemFilter")
  94. }
  95. if len(query.QuotaType) > 0 {
  96. q = q.Equals("quota_type", query.QuotaType)
  97. }
  98. if len(query.QuotaRange) > 0 {
  99. q = q.Equals("quota_range", query.QuotaRange)
  100. }
  101. return q, nil
  102. }
  103. func (man *SCloudproviderQuotaManager) OrderByExtraFields(
  104. ctx context.Context,
  105. q *sqlchemy.SQuery,
  106. userCred mcclient.TokenCredential,
  107. query api.CloudproviderQuotaListInput,
  108. ) (*sqlchemy.SQuery, error) {
  109. q, err := man.SStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StandaloneResourceListInput)
  110. if err != nil {
  111. return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.OrderByExtraFields")
  112. }
  113. q, err = man.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
  114. if err != nil {
  115. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
  116. }
  117. q, err = man.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
  118. if err != nil {
  119. return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
  120. }
  121. return q, nil
  122. }
  123. func (man *SCloudproviderQuotaManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  124. q, err := man.SStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
  125. if err == nil {
  126. return q, nil
  127. }
  128. q, err = man.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
  129. if err == nil {
  130. return q, nil
  131. }
  132. q, err = man.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
  133. if err == nil {
  134. return q, nil
  135. }
  136. return q, httperrors.ErrNotFound
  137. }
  138. func (manager *SCloudproviderQuotaManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  139. var err error
  140. q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
  141. if err == nil {
  142. return q, nil
  143. }
  144. return q, httperrors.ErrNotFound
  145. }
  146. func (manager *SCloudproviderQuotaManager) FetchCustomizeColumns(
  147. ctx context.Context,
  148. userCred mcclient.TokenCredential,
  149. query jsonutils.JSONObject,
  150. objs []interface{},
  151. fields stringutils2.SSortedStrings,
  152. isList bool,
  153. ) []api.CloudproviderQuotaDetails {
  154. rows := make([]api.CloudproviderQuotaDetails, len(objs))
  155. stdRows := manager.SStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  156. manRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  157. regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  158. for i := range rows {
  159. rows[i] = api.CloudproviderQuotaDetails{
  160. StandaloneResourceDetails: stdRows[i],
  161. ManagedResourceInfo: manRows[i],
  162. CloudregionResourceInfo: regRows[i],
  163. }
  164. }
  165. return rows
  166. }
  167. func (manager *SCloudproviderQuotaManager) GetQuotas(provider *SCloudprovider, region *SCloudregion, quotaRange string) ([]SCloudproviderQuota, error) {
  168. q := manager.Query()
  169. if provider != nil {
  170. q = q.Equals("manager_id", provider.Id)
  171. }
  172. if region != nil {
  173. q = q.Equals("cloudregion_id", region.Id)
  174. }
  175. if len(quotaRange) > 0 {
  176. q = q.Equals("quota_range", quotaRange)
  177. }
  178. quotas := []SCloudproviderQuota{}
  179. err := db.FetchModelObjects(manager, q, &quotas)
  180. if err != nil {
  181. return nil, errors.Wrap(err, "db.FetchModelObjects")
  182. }
  183. return quotas, nil
  184. }
  185. func (manager *SCloudproviderQuotaManager) SyncQuotas(ctx context.Context, userCred mcclient.TokenCredential, syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider, region *SCloudregion, quotaRange string, iQuotas []cloudprovider.ICloudQuota, xor bool) compare.SyncResult {
  186. key := provider.Id
  187. if region != nil {
  188. key = fmt.Sprintf("%s-%s", key, region.Id)
  189. }
  190. lockman.LockRawObject(ctx, manager.Keyword(), key)
  191. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), key)
  192. result := compare.SyncResult{}
  193. dbQuotas, err := manager.GetQuotas(provider, region, quotaRange)
  194. if err != nil {
  195. result.Error(errors.Wrapf(err, "GetQuotas"))
  196. return result
  197. }
  198. removed := make([]SCloudproviderQuota, 0)
  199. commondb := make([]SCloudproviderQuota, 0)
  200. commonext := make([]cloudprovider.ICloudQuota, 0)
  201. added := make([]cloudprovider.ICloudQuota, 0)
  202. err = compare.CompareSets(dbQuotas, iQuotas, &removed, &commondb, &commonext, &added)
  203. if err != nil {
  204. result.Error(errors.Wrapf(err, "CompareSets"))
  205. return result
  206. }
  207. for i := 0; i < len(removed); i++ {
  208. err := removed[i].Delete(ctx, userCred)
  209. if err != nil {
  210. result.DeleteError(err)
  211. } else {
  212. result.Delete()
  213. }
  214. }
  215. if !xor {
  216. for i := 0; i < len(commondb); i++ {
  217. err := commondb[i].SyncWithCloudQuota(ctx, userCred, commonext[i])
  218. if err != nil {
  219. result.UpdateError(err)
  220. continue
  221. }
  222. result.Update()
  223. }
  224. }
  225. for i := 0; i < len(added); i++ {
  226. err = manager.newFromCloudQuota(ctx, userCred, provider, region, quotaRange, added[i])
  227. if err != nil {
  228. result.AddError(err)
  229. continue
  230. }
  231. result.Add()
  232. }
  233. return result
  234. }
  235. func (self *SCloudproviderQuota) SyncWithCloudQuota(ctx context.Context, userCred mcclient.TokenCredential, iQuota cloudprovider.ICloudQuota) error {
  236. _, err := db.UpdateWithLock(ctx, self, func() error {
  237. self.UsedCount = int64(iQuota.GetCurrentQuotaUsedCount())
  238. self.MaxCount = int64(iQuota.GetMaxQuotaCount())
  239. return nil
  240. })
  241. return err
  242. }
  243. func (manager *SCloudproviderQuotaManager) newFromCloudQuota(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, quotaRange string, iQuota cloudprovider.ICloudQuota) error {
  244. quota := SCloudproviderQuota{}
  245. quota.SetModelManager(manager, &quota)
  246. quota.Name = iQuota.GetQuotaType()
  247. quota.Description = iQuota.GetDesc()
  248. quota.ExternalId = iQuota.GetGlobalId()
  249. quota.ManagerId = provider.Id
  250. quota.QuotaType = iQuota.GetQuotaType()
  251. quota.QuotaRange = quotaRange
  252. quota.UsedCount = int64(iQuota.GetCurrentQuotaUsedCount())
  253. quota.MaxCount = int64(iQuota.GetMaxQuotaCount())
  254. if region != nil {
  255. quota.CloudregionId = region.Id
  256. }
  257. return manager.TableSpec().Insert(ctx, &quota)
  258. }
  259. func (manager *SCloudproviderQuotaManager) ListItemExportKeys(ctx context.Context,
  260. q *sqlchemy.SQuery,
  261. userCred mcclient.TokenCredential,
  262. keys stringutils2.SSortedStrings,
  263. ) (*sqlchemy.SQuery, error) {
  264. var err error
  265. q, err = manager.SStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  266. if err != nil {
  267. return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.ListItemExportKeys")
  268. }
  269. if keys.ContainsAny(manager.SCloudregionResourceBaseManager.GetExportKeys()...) {
  270. q, err = manager.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  271. if err != nil {
  272. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
  273. }
  274. }
  275. if keys.ContainsAny(manager.SManagedResourceBaseManager.GetExportKeys()...) {
  276. q, err = manager.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  277. if err != nil {
  278. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
  279. }
  280. }
  281. return q, nil
  282. }