identityquota.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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/util/rbacscope"
  20. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  21. "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
  22. commonOptions "yunion.io/x/onecloud/pkg/cloudcommon/options"
  23. "yunion.io/x/onecloud/pkg/keystone/options"
  24. "yunion.io/x/onecloud/pkg/mcclient"
  25. )
  26. type SQuotaManager struct {
  27. quotas.SQuotaBaseManager
  28. }
  29. var (
  30. IdentityQuota SIdentityQuota
  31. IdentityQuotaManager *SQuotaManager
  32. IdentityUsageManager *SQuotaManager
  33. IdentityPendingUsageManager *SQuotaManager
  34. )
  35. func init() {
  36. IdentityQuota = SIdentityQuota{}
  37. IdentityUsageManager = &SQuotaManager{
  38. SQuotaBaseManager: quotas.NewQuotaUsageManager(IdentityQuota,
  39. rbacscope.ScopeDomain,
  40. "identity_quota_usage_tbl",
  41. "identity_quota_usage",
  42. "identity_quota_usages",
  43. ),
  44. }
  45. IdentityPendingUsageManager = &SQuotaManager{
  46. SQuotaBaseManager: quotas.NewQuotaUsageManager(IdentityQuota,
  47. rbacscope.ScopeDomain,
  48. "identity_quota_pending_usage_tbl",
  49. "identity_quota_pending_usage",
  50. "identity_quota_pending_usages",
  51. ),
  52. }
  53. IdentityQuotaManager = &SQuotaManager{
  54. SQuotaBaseManager: quotas.NewQuotaBaseManager(IdentityQuota,
  55. rbacscope.ScopeDomain,
  56. "identity_quota_tbl",
  57. IdentityPendingUsageManager,
  58. IdentityUsageManager,
  59. "identity_quota",
  60. "identity_quotas",
  61. ),
  62. }
  63. quotas.Register(IdentityQuotaManager)
  64. }
  65. type SIdentityQuota struct {
  66. quotas.SQuotaBase
  67. quotas.SBaseDomainQuotaKeys
  68. User int `default:"-1" allow_zero:"true" json:"user"`
  69. Group int `default:"-1" allow_zero:"true" json:"group"`
  70. Project int `default:"-1" allow_zero:"true" json:"project"`
  71. Role int `default:"-1" allow_zero:"true" json:"role"`
  72. Policy int `default:"-1" allow_zero:"true" json:"policy"`
  73. }
  74. func (self *SIdentityQuota) GetKeys() quotas.IQuotaKeys {
  75. return self.SBaseDomainQuotaKeys
  76. }
  77. func (self *SIdentityQuota) SetKeys(keys quotas.IQuotaKeys) {
  78. self.SBaseDomainQuotaKeys = keys.(quotas.SBaseDomainQuotaKeys)
  79. }
  80. func (self *SIdentityQuota) FetchSystemQuota() {
  81. base := 0
  82. switch options.Options.DefaultQuotaValue {
  83. case commonOptions.DefaultQuotaUnlimit:
  84. base = -1
  85. case commonOptions.DefaultQuotaZero:
  86. base = 0
  87. case commonOptions.DefaultQuotaDefault:
  88. base = 1
  89. }
  90. defaultValue := func(def int) int {
  91. if base < 0 {
  92. return -1
  93. } else {
  94. return def * base
  95. }
  96. }
  97. self.User = defaultValue(options.Options.DefaultUserQuota)
  98. self.Group = defaultValue(options.Options.DefaultGroupQuota)
  99. self.Project = defaultValue(options.Options.DefaultProjectQuota)
  100. self.Role = defaultValue(options.Options.DefaultRoleQuota)
  101. self.Policy = defaultValue(options.Options.DefaultPolicyQuota)
  102. }
  103. func (self *SIdentityQuota) FetchUsage(ctx context.Context) error {
  104. keys := self.SBaseDomainQuotaKeys
  105. scope := keys.Scope()
  106. ownerId := keys.OwnerId()
  107. self.User = UserManager.totalCount(scope, ownerId)
  108. self.Group = GroupManager.totalCount(scope, ownerId)
  109. self.Project = ProjectManager.totalCount(scope, ownerId)
  110. self.Role = RoleManager.totalCount(scope, ownerId)
  111. self.Policy = PolicyManager.totalCount(scope, ownerId)
  112. return nil
  113. }
  114. func (self *SIdentityQuota) ResetNegative() {
  115. if self.User < 0 {
  116. self.User = 0
  117. }
  118. if self.Group < 0 {
  119. self.Group = 0
  120. }
  121. if self.Project < 0 {
  122. self.Project = 0
  123. }
  124. if self.Role < 0 {
  125. self.Role = 0
  126. }
  127. if self.Policy < 0 {
  128. self.Policy = 0
  129. }
  130. }
  131. func (self *SIdentityQuota) IsEmpty() bool {
  132. if self.User > 0 {
  133. return false
  134. }
  135. if self.Group > 0 {
  136. return false
  137. }
  138. if self.Project > 0 {
  139. return false
  140. }
  141. if self.Role > 0 {
  142. return false
  143. }
  144. if self.Policy > 0 {
  145. return false
  146. }
  147. return true
  148. }
  149. func (self *SIdentityQuota) Add(quota quotas.IQuota) {
  150. squota := quota.(*SIdentityQuota)
  151. self.User = self.User + quotas.NonNegative(squota.User)
  152. self.Group = self.Group + quotas.NonNegative(squota.Group)
  153. self.Project = self.Project + quotas.NonNegative(squota.Project)
  154. self.Role = self.Role + quotas.NonNegative(squota.Role)
  155. self.Policy = self.Policy + quotas.NonNegative(squota.Policy)
  156. }
  157. func (self *SIdentityQuota) Sub(quota quotas.IQuota) {
  158. squota := quota.(*SIdentityQuota)
  159. self.User = quotas.NonNegative(self.User - squota.User)
  160. self.Group = quotas.NonNegative(self.Group - squota.Group)
  161. self.Project = quotas.NonNegative(self.Project - squota.Project)
  162. self.Role = quotas.NonNegative(self.Role - squota.Role)
  163. self.Policy = quotas.NonNegative(self.Policy - squota.Policy)
  164. }
  165. func (self *SIdentityQuota) Allocable(request quotas.IQuota) int {
  166. squota := request.(*SIdentityQuota)
  167. cnt := -1
  168. if self.User >= 0 && squota.User > 0 && (cnt < 0 || cnt > self.User/squota.User) {
  169. cnt = self.User / squota.User
  170. }
  171. if self.Group >= 0 && squota.Group > 0 && (cnt < 0 || cnt > self.Group/squota.Group) {
  172. cnt = self.Group / squota.Group
  173. }
  174. if self.Project >= 0 && squota.Project > 0 && (cnt < 0 || cnt > self.Project/squota.Project) {
  175. cnt = self.Project / squota.Project
  176. }
  177. if self.Role >= 0 && squota.Role > 0 && (cnt < 0 || cnt > self.Role/squota.Role) {
  178. cnt = self.Role / squota.Role
  179. }
  180. if self.Policy >= 0 && squota.Policy > 0 && (cnt < 0 || cnt > self.Policy/squota.Policy) {
  181. cnt = self.Policy / squota.Policy
  182. }
  183. return cnt
  184. }
  185. func (self *SIdentityQuota) Update(quota quotas.IQuota) {
  186. squota := quota.(*SIdentityQuota)
  187. if squota.User > 0 {
  188. self.User = squota.User
  189. }
  190. if squota.Group > 0 {
  191. self.Group = squota.Group
  192. }
  193. if squota.Project > 0 {
  194. self.Project = squota.Project
  195. }
  196. if squota.Role > 0 {
  197. self.Role = squota.Role
  198. }
  199. if squota.Policy > 0 {
  200. self.Policy = squota.Policy
  201. }
  202. }
  203. func (used *SIdentityQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
  204. err := quotas.NewOutOfQuotaError()
  205. sreq := request.(*SIdentityQuota)
  206. squota := quota.(*SIdentityQuota)
  207. if quotas.Exceed(used.User, sreq.User, squota.User) {
  208. err.Add(used, "user", squota.User, used.User, sreq.User)
  209. }
  210. if quotas.Exceed(used.Group, sreq.Group, squota.Group) {
  211. err.Add(used, "group", squota.Group, used.Group, sreq.Group)
  212. }
  213. if quotas.Exceed(used.Project, sreq.Project, squota.Project) {
  214. err.Add(used, "project", squota.Project, used.Project, sreq.Project)
  215. }
  216. if quotas.Exceed(used.Role, sreq.Role, squota.Role) {
  217. err.Add(used, "role", squota.Role, used.Role, sreq.Role)
  218. }
  219. if quotas.Exceed(used.Policy, sreq.Policy, squota.Policy) {
  220. err.Add(used, "policy", squota.Policy, used.Policy, sreq.Policy)
  221. }
  222. if err.IsError() {
  223. return err
  224. } else {
  225. return nil
  226. }
  227. }
  228. func (self *SIdentityQuota) ToJSON(prefix string) jsonutils.JSONObject {
  229. ret := jsonutils.NewDict()
  230. ret.Add(jsonutils.NewInt(int64(self.User)), quotas.KeyName(prefix, "user"))
  231. ret.Add(jsonutils.NewInt(int64(self.Group)), quotas.KeyName(prefix, "group"))
  232. ret.Add(jsonutils.NewInt(int64(self.Project)), quotas.KeyName(prefix, "project"))
  233. ret.Add(jsonutils.NewInt(int64(self.Role)), quotas.KeyName(prefix, "role"))
  234. ret.Add(jsonutils.NewInt(int64(self.Policy)), quotas.KeyName(prefix, "policy"))
  235. return ret
  236. }
  237. func (manager *SQuotaManager) FetchIdNames(ctx context.Context, idMap map[string]map[string]string) (map[string]map[string]string, error) {
  238. for field := range idMap {
  239. switch field {
  240. case "domain_id":
  241. fieldIdMap, err := db.FetchIdNameMap(DomainManager, idMap[field])
  242. if err != nil {
  243. return nil, errors.Wrap(err, "db.FetchIdNameMap")
  244. }
  245. idMap[field] = fieldIdMap
  246. }
  247. }
  248. return idMap, nil
  249. }
  250. func (manager *SQuotaManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
  251. return db.FetchDomainInfo(ctx, data)
  252. }
  253. ///////////////////////////////////////////////////
  254. // for swagger API documentation
  255. // 域的认证配额详情
  256. type SIdentityQuotaDetail struct {
  257. SIdentityQuota
  258. quotas.SBaseDomainQuotaDetailKeys
  259. }
  260. // +onecloud:swagger-gen-route-method=GET
  261. // +onecloud:swagger-gen-route-path=/identity_quotas/domains/{domainId}
  262. // +onecloud:swagger-gen-route-tag=identity_quota
  263. // +onecloud:swagger-gen-param-path=domainId
  264. // +onecloud:swagger-gen-param-path=指定域的ID
  265. // +onecloud:swagger-gen-param-query-index=0
  266. // +onecloud:swagger-gen-resp-index=0
  267. // +onecloud:swagger-gen-resp-body-key=identity_quotas
  268. // +onecloud:swagger-gen-resp-body-list
  269. // 获取指定域的认证配额
  270. func GetIdentityQuota(query quotas.SBaseQuotaQueryInput) *SIdentityQuotaDetail {
  271. return nil
  272. }
  273. // +onecloud:swagger-gen-route-method=GET
  274. // +onecloud:swagger-gen-route-path=/identity_quotas/domains
  275. // +onecloud:swagger-gen-route-tag=identity_quota
  276. // +onecloud:swagger-gen-param-query-index=0
  277. // +onecloud:swagger-gen-resp-index=0
  278. // +onecloud:swagger-gen-resp-body-key=identity_quotas
  279. // +onecloud:swagger-gen-resp-body-list
  280. // 获取所有域的域配额
  281. func ListIdentityQuotas(query quotas.SBaseQuotaQueryInput) *SIdentityQuotaDetail {
  282. return nil
  283. }
  284. // 设置域的认证配额输入参数
  285. type SetIdentityQuotaInput struct {
  286. quotas.SBaseQuotaSetInput
  287. SIdentityQuota
  288. }
  289. // +onecloud:swagger-gen-route-method=POST
  290. // +onecloud:swagger-gen-route-path=/identity_quotas/domains/{domainId}
  291. // +onecloud:swagger-gen-route-tag=identity_quota
  292. // +onecloud:swagger-gen-param-path=domainId
  293. // +onecloud:swagger-gen-param-path=指定域的ID
  294. // +onecloud:swagger-gen-param-body-index=0
  295. // +onecloud:swagger-gen-param-body-key=identity_quotas
  296. // +onecloud:swagger-gen-resp-index=0
  297. // +onecloud:swagger-gen-resp-body-key=identity_quotas
  298. // +onecloud:swagger-gen-resp-body-list
  299. // 设置域的认证配额
  300. func SetIdentityQuotas(input SetIdentityQuotaInput) *SIdentityQuotaDetail {
  301. return nil
  302. }