Files
cloudpods/pkg/image/models/quotas.go
2022-12-27 01:21:26 +08:00

317 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/rbacscope"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
api "yunion.io/x/onecloud/pkg/apis/image"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
commonOptions "yunion.io/x/onecloud/pkg/cloudcommon/options"
"yunion.io/x/onecloud/pkg/image/options"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/utils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SQuotaManager struct {
quotas.SQuotaBaseManager
}
var (
ImageQuota SQuota
QuotaManager *SQuotaManager
QuotaUsageManager *SQuotaManager
QuotaPendingUsageManager *SQuotaManager
)
func init() {
ImageQuota = SQuota{}
QuotaPendingUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(SQuota{},
rbacscope.ScopeProject,
"quota_pending_usage_tbl",
"quota_pending_usage",
"quota_pending_usages",
),
}
QuotaUsageManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaUsageManager(SQuota{},
rbacscope.ScopeProject,
"quota_usage_tbl",
"quota_usage",
"quota_usages",
),
}
QuotaManager = &SQuotaManager{
SQuotaBaseManager: quotas.NewQuotaBaseManager(SQuota{},
rbacscope.ScopeProject,
"quota_tbl",
QuotaPendingUsageManager,
QuotaUsageManager,
"image_quota",
"image_quotas",
),
}
quotas.Register(QuotaManager)
}
type SQuota struct {
quotas.SQuotaBase
SImageQuotaKeys
Image int `default:"-1" allow_zero:"true"`
}
func (self *SQuota) GetKeys() quotas.IQuotaKeys {
return self.SImageQuotaKeys
}
func (self *SQuota) SetKeys(keys quotas.IQuotaKeys) {
self.SImageQuotaKeys = keys.(SImageQuotaKeys)
}
func (self *SQuota) FetchSystemQuota() {
keys := self.SImageQuotaKeys
base := 0
switch options.Options.DefaultQuotaValue {
case commonOptions.DefaultQuotaUnlimit:
base = -1
case commonOptions.DefaultQuotaZero:
base = 0
if keys.Scope() == rbacscope.ScopeDomain { // domain level quota
base = 10
} else if keys.DomainId == identityapi.DEFAULT_DOMAIN_ID && keys.ProjectId == auth.AdminCredential().GetProjectId() {
base = 1
}
case commonOptions.DefaultQuotaDefault:
base = 1
if keys.Scope() == rbacscope.ScopeDomain {
base = 10
}
}
defaultValue := func(def int) int {
if base < 0 {
return -1
} else {
return def * base
}
}
self.Image = defaultValue(options.Options.DefaultImageQuota)
}
func (self *SQuota) FetchUsage(ctx context.Context) error {
keys := self.SImageQuotaKeys
scope := keys.Scope()
ownerId := keys.OwnerId()
var isISO tristate.TriState
if keys.Type == string(api.ImageTypeISO) {
isISO = tristate.True
} else if keys.Type == string(api.ImageTypeTemplate) {
isISO = tristate.False
} else {
isISO = tristate.None
}
count := ImageManager.count(scope, ownerId, "", isISO, false, tristate.None, rbacutils.SPolicyResult{})
self.Image = int(count["total"].Count)
return nil
}
func (self *SQuota) ResetNegative() {
if self.Image < 0 {
self.Image = 0
}
}
func (self *SQuota) IsEmpty() bool {
if self.Image > 0 {
return false
}
return true
}
func (self *SQuota) Add(quota quotas.IQuota) {
squota := quota.(*SQuota)
self.Image = self.Image + quotas.NonNegative(squota.Image)
}
func (self *SQuota) Sub(quota quotas.IQuota) {
squota := quota.(*SQuota)
self.Image = quotas.NonNegative(self.Image - squota.Image)
}
func (self *SQuota) Allocable(request quotas.IQuota) int {
squota := request.(*SQuota)
cnt := -1
if self.Image >= 0 && squota.Image > 0 && (cnt < 0 || cnt > self.Image/squota.Image) {
cnt = self.Image / squota.Image
}
return cnt
}
func (self *SQuota) Update(quota quotas.IQuota) {
squota := quota.(*SQuota)
if squota.Image > 0 {
self.Image = squota.Image
}
}
func (used *SQuota) Exceed(request quotas.IQuota, quota quotas.IQuota) error {
err := quotas.NewOutOfQuotaError()
sreq := request.(*SQuota)
squota := quota.(*SQuota)
if quotas.Exceed(used.Image, sreq.Image, squota.Image) {
err.Add(used, "image", squota.Image, used.Image, sreq.Image)
}
if err.IsError() {
return err
} else {
return nil
}
}
func (self *SQuota) ToJSON(prefix string) jsonutils.JSONObject {
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewInt(int64(self.Image)), quotas.KeyName(prefix, "image"))
return ret
}
func (manager *SQuotaManager) FetchIdNames(ctx context.Context, idMap map[string]map[string]string) (map[string]map[string]string, error) {
for field := range idMap {
switch field {
case "domain_id":
fieldIdMap, err := utils.FetchDomainNames(ctx, idMap[field])
if err != nil {
return nil, errors.Wrap(err, "utils.FetchDomainNames")
}
idMap[field] = fieldIdMap
case "tenant_id":
fieldIdMap, err := utils.FetchTenantNames(ctx, idMap[field])
if err != nil {
return nil, errors.Wrap(err, "utils.FetchTenantNames")
}
idMap[field] = fieldIdMap
}
}
return idMap, nil
}
type SImageQuotaKeys struct {
quotas.SBaseProjectQuotaKeys
Type string `width:"16" charset:"ascii" nullable:"false" primary:"true" list:"user"`
}
func (k SImageQuotaKeys) Fields() []string {
return append(k.SBaseProjectQuotaKeys.Fields(), "type")
}
func (k SImageQuotaKeys) Values() []string {
return append(k.SBaseProjectQuotaKeys.Values(), k.Type)
}
func (k1 SImageQuotaKeys) Compare(ik quotas.IQuotaKeys) int {
k2 := ik.(SImageQuotaKeys)
r := k1.SBaseProjectQuotaKeys.Compare(k2.SBaseProjectQuotaKeys)
if r != 0 {
return r
}
if k1.Type < k2.Type {
return -1
} else if k1.Type > k2.Type {
return 1
}
return 0
}
///////////////////////////////////////////////////
// for swagger API documentation
// 区域配额详情
type SImageQuotaDetail struct {
SQuota
quotas.SBaseProjectQuotaDetailKeys
}
// +onecloud:swagger-gen-route-method=GET
// +onecloud:swagger-gen-route-path=/image_quotas/{scope}/{scopeId}
// +onecloud:swagger-gen-route-tag=image_quota
// +onecloud:swagger-gen-param-path=scope
// +onecloud:swagger-gen-param-path=配额所属范围可能值为projects和domains分别代表项目的配额和域的配额
// +onecloud:swagger-gen-param-path=scopeId
// +onecloud:swagger-gen-param-path=指定项目或者域的ID
// +onecloud:swagger-gen-param-query-index=0
// +onecloud:swagger-gen-resp-index=0
// +onecloud:swagger-gen-resp-body-key=image_quotas
// +onecloud:swagger-gen-resp-body-list
// 获取指定项目或者域的镜像配额
func GetImageQuota(query quotas.SBaseQuotaQueryInput) *SImageQuotaDetail {
return nil
}
// +onecloud:swagger-gen-route-method=GET
// +onecloud:swagger-gen-route-path=/image_quotas/{scope}
// +onecloud:swagger-gen-route-tag=image_quota
// +onecloud:swagger-gen-param-path=scope
// +onecloud:swagger-gen-param-path=配额所属范围可能值为projects和domains分别代表项 目的配额和域的配额
// +onecloud:swagger-gen-param-query-index=0
// +onecloud:swagger-gen-resp-index=0
// +onecloud:swagger-gen-resp-body-key=image_quotas
// +onecloud:swagger-gen-resp-body-list
// 获取所有项目或者域的镜像配额
func ListImageQuotas(query quotas.SBaseQuotaQueryInput) *SImageQuotaDetail {
return nil
}
// 设置镜像配额输入参数
type SetImageQuotaInput struct {
quotas.SBaseQuotaSetInput
SQuota
}
// +onecloud:swagger-gen-route-method=POST
// +onecloud:swagger-gen-route-path=/image_quotas/{scope}/{scopeId}
// +onecloud:swagger-gen-route-tag=image_quota
// +onecloud:swagger-gen-param-path=scope
// +onecloud:swagger-gen-param-path=配额所属范围可能值为projects和domains分别代表项目的配额和域的配额
// +onecloud:swagger-gen-param-path=scopeId
// +onecloud:swagger-gen-param-path=指定项目或者域的ID
// +onecloud:swagger-gen-param-body-index=0
// +onecloud:swagger-gen-param-body-key=image_quotas
// +onecloud:swagger-gen-resp-index=0
// +onecloud:swagger-gen-resp-body-key=image_quotas
// +onecloud:swagger-gen-resp-body-list
// 设置指定项目或者域的镜像配额
func SetRegionQuotas(input SetImageQuotaInput) *SImageQuotaDetail {
return nil
}