infrasquota.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. "yunion.io/x/jsonutils"
  18. "yunion.io/x/pkg/errors"
  19. "yunion.io/x/pkg/tristate"
  20. "yunion.io/x/pkg/util/rbacscope"
  21. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  22. "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
  23. commonOptions "yunion.io/x/onecloud/pkg/cloudcommon/options"
  24. "yunion.io/x/onecloud/pkg/compute/options"
  25. "yunion.io/x/onecloud/pkg/util/rbacutils"
  26. )
  27. var (
  28. InfrasQuota SInfrasQuota
  29. InfrasQuotaManager *SQuotaManager
  30. InfrasUsageManager *SQuotaManager
  31. InfrasPendingUsageManager *SQuotaManager
  32. )
  33. func init() {
  34. InfrasQuota = SInfrasQuota{}
  35. InfrasUsageManager = &SQuotaManager{
  36. SQuotaBaseManager: quotas.NewQuotaUsageManager(InfrasQuota,
  37. rbacscope.ScopeDomain,
  38. "infras_quota_usage_tbl",
  39. "infras_quota_usage",
  40. "infras_quota_usages",
  41. ),
  42. }
  43. InfrasPendingUsageManager = &SQuotaManager{
  44. SQuotaBaseManager: quotas.NewQuotaUsageManager(InfrasQuota,
  45. rbacscope.ScopeDomain,
  46. "infras_quota_pending_usage_tbl",
  47. "infras_quota_pending_usage",
  48. "infras_quota_pending_usages",
  49. ),
  50. }
  51. InfrasQuotaManager = &SQuotaManager{
  52. SQuotaBaseManager: quotas.NewQuotaBaseManager(InfrasQuota,
  53. rbacscope.ScopeDomain,
  54. "infras_quota_tbl",
  55. InfrasPendingUsageManager,
  56. InfrasUsageManager,
  57. "infras_quota",
  58. "infras_quotas",
  59. ),
  60. }
  61. quotas.Register(InfrasQuotaManager)
  62. }
  63. type SInfrasQuota struct {
  64. quotas.SQuotaBase
  65. quotas.SDomainRegionalCloudResourceKeys
  66. Host int `default:"-1" allow_zero:"true" json:"host"`
  67. Vpc int `default:"-1" allow_zero:"true" json:"vpc"`
  68. }
  69. func (self *SInfrasQuota) GetKeys() quotas.IQuotaKeys {
  70. return self.SDomainRegionalCloudResourceKeys
  71. }
  72. func (self *SInfrasQuota) SetKeys(keys quotas.IQuotaKeys) {
  73. self.SDomainRegionalCloudResourceKeys = keys.(quotas.SDomainRegionalCloudResourceKeys)
  74. }
  75. func (self *SInfrasQuota) FetchSystemQuota() {
  76. base := 0
  77. switch options.Options.DefaultQuotaValue {
  78. case commonOptions.DefaultQuotaUnlimit:
  79. base = -1
  80. case commonOptions.DefaultQuotaZero:
  81. base = 0
  82. case commonOptions.DefaultQuotaDefault:
  83. base = 1
  84. }
  85. defaultValue := func(def int) int {
  86. if base < 0 {
  87. return -1
  88. } else {
  89. return def * base
  90. }
  91. }
  92. self.Host = defaultValue(options.Options.DefaultHostQuota)
  93. self.Vpc = defaultValue(options.Options.DefaultVpcQuota)
  94. }
  95. func (self *SInfrasQuota) FetchUsage(ctx context.Context) error {
  96. regionKeys := self.SDomainRegionalCloudResourceKeys
  97. scope := regionKeys.Scope()
  98. ownerId := regionKeys.OwnerId()
  99. var rangeObjs []db.IStandaloneModel
  100. if len(regionKeys.RegionId) > 0 {
  101. obj, err := CloudregionManager.FetchById(regionKeys.RegionId)
  102. if err != nil {
  103. return errors.Wrap(err, "CloudregionManager.FetchById")
  104. }
  105. rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
  106. }
  107. if len(regionKeys.ManagerId) > 0 {
  108. obj, err := CloudproviderManager.FetchById(regionKeys.ManagerId)
  109. if err != nil {
  110. return errors.Wrap(err, "CloudproviderManager.FetchById")
  111. }
  112. rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
  113. } else if len(regionKeys.AccountId) > 0 {
  114. obj, err := CloudaccountManager.FetchById(regionKeys.AccountId)
  115. if err != nil {
  116. return errors.Wrap(err, "CloudaccountManager.FetchById")
  117. }
  118. rangeObjs = append(rangeObjs, obj.(db.IStandaloneModel))
  119. }
  120. var providers []string
  121. if len(regionKeys.Provider) > 0 {
  122. providers = []string{regionKeys.Provider}
  123. }
  124. var brands []string
  125. if len(regionKeys.Brand) > 0 {
  126. brands = []string{regionKeys.Brand}
  127. }
  128. hostStat := HostManager.TotalCount(ctx, ownerId, scope, rangeObjs, "", "", nil, nil, providers, brands, regionKeys.CloudEnv, tristate.None, tristate.None, rbacutils.SPolicyResult{})
  129. self.Host = int(hostStat.Count)
  130. self.Vpc = VpcManager.totalCount(ctx, ownerId, scope, rangeObjs, providers, brands, regionKeys.CloudEnv)
  131. return nil
  132. }
  133. func (self *SInfrasQuota) ResetNegative() {
  134. if self.Host < 0 {
  135. self.Host = 0
  136. }
  137. if self.Vpc < 0 {
  138. self.Vpc = 0
  139. }
  140. }
  141. func (self *SInfrasQuota) IsEmpty() bool {
  142. if self.Host > 0 {
  143. return false
  144. }
  145. if self.Vpc > 0 {
  146. return false
  147. }
  148. return true
  149. }
  150. func (self *SInfrasQuota) Add(quota quotas.IQuota) {
  151. squota := quota.(*SInfrasQuota)
  152. self.Host = self.Host + quotas.NonNegative(squota.Host)
  153. self.Vpc = self.Vpc + quotas.NonNegative(squota.Vpc)
  154. }
  155. func (self *SInfrasQuota) Sub(quota quotas.IQuota) {
  156. squota := quota.(*SInfrasQuota)
  157. self.Host = nonNegative(self.Host - squota.Host)
  158. self.Vpc = nonNegative(self.Vpc - squota.Vpc)
  159. }
  160. func (self *SInfrasQuota) Allocable(request quotas.IQuota) int {
  161. squota := request.(*SInfrasQuota)
  162. cnt := -1
  163. if self.Host >= 0 && squota.Host > 0 && (cnt < 0 || cnt > self.Host/squota.Host) {
  164. cnt = self.Host / squota.Host
  165. }
  166. if self.Vpc >= 0 && squota.Vpc > 0 && (cnt < 0 || cnt > self.Vpc/squota.Vpc) {
  167. cnt = self.Vpc / squota.Vpc
  168. }
  169. return cnt
  170. }
  171. func (self *SInfrasQuota) Update(quota quotas.IQuota) {
  172. squota := quota.(*SInfrasQuota)
  173. if squota.Host > 0 {
  174. self.Host = squota.Host
  175. }
  176. if squota.Vpc > 0 {
  177. self.Vpc = squota.Vpc
  178. }
  179. }
  180. func (used *SInfrasQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
  181. err := quotas.NewOutOfQuotaError()
  182. sreq := request.(*SInfrasQuota)
  183. squota := quota.(*SInfrasQuota)
  184. if quotas.Exceed(used.Host, sreq.Host, squota.Host) {
  185. err.Add(used, "host", squota.Host, used.Host, sreq.Host)
  186. }
  187. if quotas.Exceed(used.Vpc, sreq.Vpc, squota.Vpc) {
  188. err.Add(used, "vpc", squota.Vpc, used.Vpc, sreq.Vpc)
  189. }
  190. if err.IsError() {
  191. return err
  192. } else {
  193. return nil
  194. }
  195. }
  196. func (self *SInfrasQuota) ToJSON(prefix string) jsonutils.JSONObject {
  197. ret := jsonutils.NewDict()
  198. ret.Add(jsonutils.NewInt(int64(self.Host)), keyName(prefix, "host"))
  199. ret.Add(jsonutils.NewInt(int64(self.Vpc)), keyName(prefix, "vpc"))
  200. return ret
  201. }