mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
feature: domain resource quota
This commit is contained in:
@@ -16,6 +16,7 @@ package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
|
||||
@@ -112,3 +113,16 @@ func GenerateName2(manager IModelManager, ownerId mcclient.IIdentityProvider, hi
|
||||
baseIndex += 1
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
dnsNameREG = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9-]*$`)
|
||||
)
|
||||
|
||||
type SDnsNameValidatorManager struct{}
|
||||
|
||||
func (manager *SDnsNameValidatorManager) ValidateName(name string) error {
|
||||
if dnsNameREG.MatchString(name) {
|
||||
return nil
|
||||
}
|
||||
return httperrors.NewInputParameterError("name starts with letter, and contains letter, number and - only")
|
||||
}
|
||||
|
||||
@@ -75,10 +75,6 @@ func AddQuotaHandler(manager *SQuotaBaseManager, prefix string, app *appsrv.Appl
|
||||
fmt.Sprintf("%s/%s", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.getQuotaHandler), nil, "get_quota", nil)
|
||||
|
||||
app.AddHandler2("GET",
|
||||
fmt.Sprintf("%s/%s/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.getQuotaHandler), nil, "get_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("GET",
|
||||
fmt.Sprintf("%s/%s/domains", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.listDomainQuotaHandler), nil, "list_quotas_for_all_domains", nil)
|
||||
@@ -87,30 +83,14 @@ func AddQuotaHandler(manager *SQuotaBaseManager, prefix string, app *appsrv.Appl
|
||||
fmt.Sprintf("%s/%s/domains/<domainid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.getQuotaHandler), nil, "get_quota_for_domain", nil)
|
||||
|
||||
app.AddHandler2("GET",
|
||||
fmt.Sprintf("%s/%s/projects", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.listProjectQuotaHandler), nil, "list_quotas_for_all_projects", nil)
|
||||
|
||||
app.AddHandler2("GET",
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.getQuotaHandler), nil, "get_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("POST",
|
||||
fmt.Sprintf("%s/%s", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.setQuotaHandler), nil, "set_quota", nil)
|
||||
|
||||
app.AddHandler2("POST",
|
||||
fmt.Sprintf("%s/%s/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.setQuotaHandler), nil, "set_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("POST",
|
||||
fmt.Sprintf("%s/%s/domains/<domainid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.setQuotaHandler), nil, "set_quota_for_domain", nil)
|
||||
|
||||
app.AddHandler2("POST",
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.setQuotaHandler), nil, "set_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("DELETE",
|
||||
fmt.Sprintf("%s/%s/pending", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.cleanPendingUsageHandler), nil, "clean_pending_usage", nil)
|
||||
@@ -119,9 +99,31 @@ func AddQuotaHandler(manager *SQuotaBaseManager, prefix string, app *appsrv.Appl
|
||||
fmt.Sprintf("%s/%s/domains/<domainid>/pending", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.cleanPendingUsageHandler), nil, "clean_pending_usage_for_domain", nil)
|
||||
|
||||
app.AddHandler2("DELETE",
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>/pending", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.cleanPendingUsageHandler), nil, "clean_pending_usage_for_project", nil)
|
||||
if manager.scope == rbacutils.ScopeProject {
|
||||
app.AddHandler2("GET",
|
||||
fmt.Sprintf("%s/%s/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.getQuotaHandler), nil, "get_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("GET",
|
||||
fmt.Sprintf("%s/%s/projects", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.listProjectQuotaHandler), nil, "list_quotas_for_all_projects", nil)
|
||||
|
||||
app.AddHandler2("GET",
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.getQuotaHandler), nil, "get_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("POST",
|
||||
fmt.Sprintf("%s/%s/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.setQuotaHandler), nil, "set_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("POST",
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.setQuotaHandler), nil, "set_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("DELETE",
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>/pending", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.cleanPendingUsageHandler), nil, "clean_pending_usage_for_project", nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) queryQuota(ctx context.Context, quota IQuota, refresh bool) (*jsonutils.JSONDict, error) {
|
||||
@@ -181,24 +183,24 @@ func (manager *SQuotaBaseManager) getQuotaHandler(ctx context.Context, w http.Re
|
||||
} else if len(projectId) > 0 {
|
||||
data.Add(jsonutils.NewString(projectId), "project")
|
||||
}
|
||||
ownerId, scope, err = db.FetchCheckQueryOwnerScope(ctx, userCred, data, manager, policy.PolicyActionGet, true)
|
||||
ownerId, scope, err = db.FetchCheckQueryOwnerScope(ctx, userCred, data, manager.GetIQuotaManager(), policy.PolicyActionGet, true)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
scopeStr, _ := query.GetString("scope")
|
||||
if scopeStr == "project" {
|
||||
if scopeStr == "project" && manager.scope == rbacutils.ScopeProject {
|
||||
scope = rbacutils.ScopeProject
|
||||
} else if scopeStr == "domain" {
|
||||
scope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
scope = rbacutils.ScopeProject
|
||||
scope = manager.scope
|
||||
}
|
||||
ownerId = userCred
|
||||
}
|
||||
|
||||
keys := OwnerIdQuotaKeys(scope, ownerId)
|
||||
keys := OwnerIdProjectQuotaKeys(scope, ownerId)
|
||||
refresh := jsonutils.QueryBoolean(query, "refresh", false)
|
||||
primary := jsonutils.QueryBoolean(query, "primary", false)
|
||||
quotaList, err := manager.listQuotas(ctx, userCred, keys.DomainId, keys.ProjectId, scope == rbacutils.ScopeDomain, primary, refresh)
|
||||
@@ -208,7 +210,12 @@ func (manager *SQuotaBaseManager) getQuotaHandler(ctx context.Context, w http.Re
|
||||
}
|
||||
if len(quotaList) == 0 {
|
||||
quota := manager.newQuota()
|
||||
baseKeys := OwnerIdQuotaKeys(scope, ownerId)
|
||||
var baseKeys IQuotaKeys
|
||||
if manager.scope == rbacutils.ScopeProject {
|
||||
baseKeys = OwnerIdProjectQuotaKeys(scope, ownerId)
|
||||
} else {
|
||||
baseKeys = OwnerIdDomainQuotaKeys(ownerId)
|
||||
}
|
||||
reflectutils.FillEmbededStructValue(reflect.Indirect(reflect.ValueOf(quota)), reflect.ValueOf(baseKeys))
|
||||
quota.FetchSystemQuota()
|
||||
manager.SetQuota(ctx, userCred, quota)
|
||||
@@ -303,11 +310,16 @@ func (manager *SQuotaBaseManager) cleanPendingUsageHandler(ctx context.Context,
|
||||
} else if scopeStr == "domain" {
|
||||
scope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
scope = rbacutils.ScopeProject
|
||||
scope = manager.scope
|
||||
}
|
||||
ownerId = userCred
|
||||
}
|
||||
keys := OwnerIdQuotaKeys(scope, ownerId)
|
||||
var keys IQuotaKeys
|
||||
if manager.scope == rbacutils.ScopeProject {
|
||||
keys = OwnerIdProjectQuotaKeys(scope, ownerId)
|
||||
} else {
|
||||
keys = OwnerIdDomainQuotaKeys(ownerId)
|
||||
}
|
||||
err = manager.cleanPendingUsage(ctx, userCred, keys)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
@@ -339,7 +351,12 @@ func (manager *SQuotaBaseManager) setQuotaHandler(ctx context.Context, w http.Re
|
||||
}
|
||||
|
||||
// check is there any nonempty key other than domain_id and project_id
|
||||
isBaseQuota := IsBaseQuotaKeys(quota.GetKeys())
|
||||
isBaseQuota := false
|
||||
if manager.scope == rbacutils.ScopeDomain {
|
||||
isBaseQuota = IsBaseDomainQuotaKeys(quota.GetKeys())
|
||||
} else {
|
||||
isBaseQuota = IsBaseProjectQuotaKeys(quota.GetKeys())
|
||||
}
|
||||
ownerId, scope, requestScope, err := manager.fetchSetQuotaScope(ctx, userCred, data, isBaseQuota)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
@@ -347,7 +364,12 @@ func (manager *SQuotaBaseManager) setQuotaHandler(ctx context.Context, w http.Re
|
||||
}
|
||||
|
||||
// fill project_id and domain_id
|
||||
baseKeys := OwnerIdQuotaKeys(scope, ownerId)
|
||||
var baseKeys IQuotaKeys
|
||||
if manager.scope == rbacutils.ScopeDomain {
|
||||
baseKeys = OwnerIdDomainQuotaKeys(ownerId)
|
||||
} else {
|
||||
baseKeys = OwnerIdProjectQuotaKeys(scope, ownerId)
|
||||
}
|
||||
reflectutils.FillEmbededStructValue(reflect.Indirect(reflect.ValueOf(quota)), reflect.ValueOf(baseKeys))
|
||||
|
||||
keys := quota.GetKeys()
|
||||
@@ -427,7 +449,7 @@ func (manager *SQuotaBaseManager) setQuotaHandler(ctx context.Context, w http.Re
|
||||
}
|
||||
}
|
||||
|
||||
quotaList, err := manager.listQuotas(ctx, userCred, baseKeys.DomainId, baseKeys.ProjectId, scope == rbacutils.ScopeDomain, false, true)
|
||||
quotaList, err := manager.listQuotas(ctx, userCred, baseKeys.OwnerId().GetProjectDomainId(), baseKeys.OwnerId().GetProjectId(), scope == rbacutils.ScopeDomain, false, true)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
return
|
||||
@@ -510,7 +532,9 @@ func (manager *SQuotaBaseManager) listQuotas(ctx context.Context, userCred mccli
|
||||
if len(targetDomainId) > 0 {
|
||||
q = q.Equals("domain_id", targetDomainId)
|
||||
if domainOnly {
|
||||
q = q.IsEmpty("tenant_id")
|
||||
if manager.scope == rbacutils.ScopeProject {
|
||||
q = q.IsEmpty("tenant_id")
|
||||
}
|
||||
} else {
|
||||
if len(targetProjectId) > 0 {
|
||||
q = q.Equals("tenant_id", targetProjectId)
|
||||
@@ -524,7 +548,9 @@ func (manager *SQuotaBaseManager) listQuotas(ctx context.Context, userCred mccli
|
||||
} else {
|
||||
// domain only
|
||||
q = q.IsNotEmpty("domain_id")
|
||||
q = q.IsNullOrEmpty("tenant_id")
|
||||
if manager.scope == rbacutils.ScopeProject {
|
||||
q = q.IsNullOrEmpty("tenant_id")
|
||||
}
|
||||
}
|
||||
if primaryOnly {
|
||||
// list primary quota for domain or project
|
||||
|
||||
@@ -38,9 +38,11 @@ type SQuotaBaseManager struct {
|
||||
usageStore IQuotaStore
|
||||
|
||||
nonNegative bool
|
||||
|
||||
scope rbacutils.TRbacScope
|
||||
}
|
||||
|
||||
func NewQuotaBaseManager(model interface{}, tableName string, pendingStore IQuotaStore, usageStore IQuotaStore, keyword, keywordPlural string) SQuotaBaseManager {
|
||||
func NewQuotaBaseManager(model interface{}, scope rbacutils.TRbacScope, tableName string, pendingStore IQuotaStore, usageStore IQuotaStore, keyword, keywordPlural string) SQuotaBaseManager {
|
||||
pendingStore.SetVirtualObject(pendingStore)
|
||||
usageStore.SetVirtualObject(usageStore)
|
||||
return SQuotaBaseManager{
|
||||
@@ -48,13 +50,15 @@ func NewQuotaBaseManager(model interface{}, tableName string, pendingStore IQuot
|
||||
pendingStore: pendingStore,
|
||||
usageStore: usageStore,
|
||||
nonNegative: false,
|
||||
scope: scope,
|
||||
}
|
||||
}
|
||||
|
||||
func NewQuotaUsageManager(model interface{}, tableName string, keyword, keywordPlural string) SQuotaBaseManager {
|
||||
func NewQuotaUsageManager(model interface{}, scope rbacutils.TRbacScope, tableName string, keyword, keywordPlural string) SQuotaBaseManager {
|
||||
return SQuotaBaseManager{
|
||||
SResourceBaseManager: db.NewResourceBaseManager(model, tableName, keyword, keywordPlural),
|
||||
nonNegative: true,
|
||||
scope: scope,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +275,12 @@ func (manager *SQuotaBaseManager) InitializeData() error {
|
||||
}
|
||||
|
||||
quota := manager.newQuota()
|
||||
baseKeys := OwnerIdQuotaKeys(scope, ownerId)
|
||||
var baseKeys IQuotaKeys
|
||||
if manager.scope == rbacutils.ScopeDomain {
|
||||
baseKeys = OwnerIdDomainQuotaKeys(ownerId)
|
||||
} else {
|
||||
baseKeys = OwnerIdProjectQuotaKeys(scope, ownerId)
|
||||
}
|
||||
if !reflectutils.FillEmbededStructValue(reflect.Indirect(reflect.ValueOf(quota)), reflect.ValueOf(baseKeys)) {
|
||||
log.Fatalf("invalid quota??? fail to find SBaseQuotaKey")
|
||||
}
|
||||
|
||||
@@ -23,22 +23,30 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
type SBaseQuotaKeys struct {
|
||||
// 配额适用的项目的域ID
|
||||
type SBaseDomainQuotaKeys struct {
|
||||
// 配额适用的域ID
|
||||
DomainId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"domain_id"`
|
||||
}
|
||||
|
||||
type SBaseProjectQuotaKeys struct {
|
||||
SBaseDomainQuotaKeys
|
||||
|
||||
// 配额适用的项目ID
|
||||
ProjectId string `name:"tenant_id" width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"project_id"`
|
||||
}
|
||||
|
||||
type SBaseQuotaDetailKeys struct {
|
||||
type SBaseDomainQuotaDetailKeys struct {
|
||||
// 配额适用的项目的域名称
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type SBaseProjectQuotaDetailKeys struct {
|
||||
SBaseDomainQuotaDetailKeys
|
||||
// 配额适用的项目名称
|
||||
Project string `json:"project"`
|
||||
}
|
||||
|
||||
type SCloudResourceKeys struct {
|
||||
SBaseQuotaKeys
|
||||
type SCloudResourceBaseKeys struct {
|
||||
// 配额适用的平台名称,参考List接口的平台列表
|
||||
Provider string `width:"32" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"provider"`
|
||||
// 配额适用的品牌名称,参考List接口的品牌列表
|
||||
@@ -51,28 +59,56 @@ type SCloudResourceKeys struct {
|
||||
ManagerId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"manager_id"`
|
||||
}
|
||||
|
||||
type SCloudResourceDetailKeys struct {
|
||||
SBaseQuotaDetailKeys
|
||||
type SCloudResourceKeys struct {
|
||||
SBaseProjectQuotaKeys
|
||||
SCloudResourceBaseKeys
|
||||
}
|
||||
|
||||
type SCloudResourceDetailKeys struct {
|
||||
SBaseProjectQuotaDetailKeys
|
||||
SCloudResourceDetailBaseKeys
|
||||
}
|
||||
|
||||
type SCloudResourceDetailBaseKeys struct {
|
||||
// 配额适用的云账号名称
|
||||
Account string `json:"account"`
|
||||
// 配额适用的云订阅名称
|
||||
Manager string `json:"manager"`
|
||||
}
|
||||
|
||||
type SRegionalCloudResourceKeys struct {
|
||||
SCloudResourceKeys
|
||||
type SRegionalBaseKeys struct {
|
||||
// 配额适用的区域ID
|
||||
RegionId string `width:"64" charset:"ascii" nullable:"false" primary:"true" list:"user" json:"region_id"`
|
||||
}
|
||||
|
||||
type SRegionalCloudResourceKeys struct {
|
||||
SCloudResourceKeys
|
||||
SRegionalBaseKeys
|
||||
}
|
||||
|
||||
type SRegionalCloudResourceDetailKeys struct {
|
||||
SCloudResourceDetailKeys
|
||||
|
||||
SRegionalCloudResourceDetailBaseKeys
|
||||
}
|
||||
|
||||
type SRegionalCloudResourceDetailBaseKeys struct {
|
||||
// 配额适用的区域名称
|
||||
Region string `json:"region"`
|
||||
}
|
||||
|
||||
type SDomainRegionalCloudResourceKeys struct {
|
||||
SBaseProjectQuotaKeys
|
||||
SCloudResourceBaseKeys
|
||||
SRegionalBaseKeys
|
||||
}
|
||||
|
||||
type SDomainRegionalCloudResourceDetailKeys struct {
|
||||
SBaseDomainQuotaDetailKeys
|
||||
SCloudResourceDetailBaseKeys
|
||||
SRegionalCloudResourceDetailBaseKeys
|
||||
}
|
||||
|
||||
type SZonalCloudResourceKeys struct {
|
||||
SRegionalCloudResourceKeys
|
||||
// 配额适用的可用区ID
|
||||
@@ -86,15 +122,20 @@ type SZonalCloudResourceDetailKeys struct {
|
||||
Zone string `json:"zone"`
|
||||
}
|
||||
|
||||
func (k SBaseQuotaKeys) Fields() []string {
|
||||
func (k SBaseDomainQuotaKeys) Fields() []string {
|
||||
return []string{
|
||||
"domain_id",
|
||||
"tenant_id",
|
||||
}
|
||||
}
|
||||
|
||||
func (k SBaseProjectQuotaKeys) Fields() []string {
|
||||
return append(k.SBaseDomainQuotaKeys.Fields(),
|
||||
"tenant_id",
|
||||
)
|
||||
}
|
||||
|
||||
func (k SCloudResourceKeys) Fields() []string {
|
||||
return append(k.SBaseQuotaKeys.Fields(),
|
||||
return append(k.SBaseProjectQuotaKeys.Fields(),
|
||||
"provider",
|
||||
"brand",
|
||||
"cloud_env",
|
||||
@@ -115,15 +156,20 @@ func (k SZonalCloudResourceKeys) Fields() []string {
|
||||
)
|
||||
}
|
||||
|
||||
func (k SBaseQuotaKeys) Values() []string {
|
||||
func (k SBaseDomainQuotaKeys) Values() []string {
|
||||
return []string{
|
||||
k.DomainId,
|
||||
k.ProjectId,
|
||||
}
|
||||
}
|
||||
|
||||
func (k SBaseProjectQuotaKeys) Values() []string {
|
||||
return append(k.SBaseDomainQuotaKeys.Values(),
|
||||
k.ProjectId,
|
||||
)
|
||||
}
|
||||
|
||||
func (k SCloudResourceKeys) Values() []string {
|
||||
return append(k.SBaseQuotaKeys.Values(),
|
||||
return append(k.SBaseProjectQuotaKeys.Values(),
|
||||
k.Provider,
|
||||
k.Brand,
|
||||
k.CloudEnv,
|
||||
@@ -144,13 +190,22 @@ func (k SZonalCloudResourceKeys) Values() []string {
|
||||
)
|
||||
}
|
||||
|
||||
func (k1 SBaseQuotaKeys) Compare(ik IQuotaKeys) int {
|
||||
k2 := ik.(SBaseQuotaKeys)
|
||||
func (k1 SBaseDomainQuotaKeys) Compare(ik IQuotaKeys) int {
|
||||
k2 := ik.(SBaseDomainQuotaKeys)
|
||||
if k1.DomainId < k2.DomainId {
|
||||
return -1
|
||||
} else if k1.DomainId > k2.DomainId {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (k1 SBaseProjectQuotaKeys) Compare(ik IQuotaKeys) int {
|
||||
k2 := ik.(SBaseProjectQuotaKeys)
|
||||
r := k1.SBaseDomainQuotaKeys.Compare(k2.SBaseDomainQuotaKeys)
|
||||
if r != 0 {
|
||||
return r
|
||||
}
|
||||
if k1.ProjectId < k2.ProjectId {
|
||||
return -1
|
||||
} else if k1.ProjectId > k2.ProjectId {
|
||||
@@ -161,7 +216,7 @@ func (k1 SBaseQuotaKeys) Compare(ik IQuotaKeys) int {
|
||||
|
||||
func (k1 SCloudResourceKeys) Compare(ik IQuotaKeys) int {
|
||||
k2 := ik.(SCloudResourceKeys)
|
||||
r := k1.SBaseQuotaKeys.Compare(k2.SBaseQuotaKeys)
|
||||
r := k1.SBaseProjectQuotaKeys.Compare(k2.SBaseProjectQuotaKeys)
|
||||
if r != 0 {
|
||||
return r
|
||||
}
|
||||
@@ -221,7 +276,15 @@ func QuotaKeyWeight(k IQuotaKeys) uint64 {
|
||||
return w
|
||||
}
|
||||
|
||||
func (k SBaseQuotaKeys) Scope() rbacutils.TRbacScope {
|
||||
func (k SBaseDomainQuotaKeys) Scope() rbacutils.TRbacScope {
|
||||
if len(k.DomainId) > 0 {
|
||||
return rbacutils.ScopeDomain
|
||||
} else {
|
||||
return rbacutils.ScopeSystem
|
||||
}
|
||||
}
|
||||
|
||||
func (k SBaseProjectQuotaKeys) Scope() rbacutils.TRbacScope {
|
||||
if len(k.DomainId) > 0 && len(k.ProjectId) > 0 {
|
||||
return rbacutils.ScopeProject
|
||||
} else if len(k.DomainId) > 0 && len(k.ProjectId) == 0 {
|
||||
@@ -233,7 +296,11 @@ func (k SBaseQuotaKeys) Scope() rbacutils.TRbacScope {
|
||||
}
|
||||
}
|
||||
|
||||
func (k SBaseQuotaKeys) OwnerId() mcclient.IIdentityProvider {
|
||||
func (k SBaseDomainQuotaKeys) OwnerId() mcclient.IIdentityProvider {
|
||||
return &db.SOwnerId{DomainId: k.DomainId}
|
||||
}
|
||||
|
||||
func (k SBaseProjectQuotaKeys) OwnerId() mcclient.IIdentityProvider {
|
||||
return &db.SOwnerId{
|
||||
DomainId: k.DomainId,
|
||||
ProjectId: k.ProjectId,
|
||||
@@ -252,7 +319,7 @@ func QuotaKeyString(k IQuotaKeys) string {
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func IsBaseQuotaKeys(k IQuotaKeys) bool {
|
||||
func IsBaseProjectQuotaKeys(k IQuotaKeys) bool {
|
||||
fields := k.Fields()
|
||||
values := k.Values()
|
||||
for i := range fields {
|
||||
@@ -263,19 +330,36 @@ func IsBaseQuotaKeys(k IQuotaKeys) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func OwnerIdQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) SBaseQuotaKeys {
|
||||
switch scope {
|
||||
case rbacutils.ScopeDomain:
|
||||
return SBaseQuotaKeys{
|
||||
DomainId: ownerId.GetProjectDomainId(),
|
||||
func IsBaseDomainQuotaKeys(k IQuotaKeys) bool {
|
||||
fields := k.Fields()
|
||||
values := k.Values()
|
||||
for i := range fields {
|
||||
if fields[i] != "domain_id" && len(values[i]) > 0 {
|
||||
return false
|
||||
}
|
||||
case rbacutils.ScopeProject:
|
||||
return SBaseQuotaKeys{
|
||||
DomainId: ownerId.GetProjectDomainId(),
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func OwnerIdProjectQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) SBaseProjectQuotaKeys {
|
||||
if scope == rbacutils.ScopeDomain {
|
||||
return SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: ownerId.GetProjectDomainId(),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: ownerId.GetProjectDomainId(),
|
||||
},
|
||||
ProjectId: ownerId.GetProjectId(),
|
||||
}
|
||||
}
|
||||
return SBaseQuotaKeys{}
|
||||
}
|
||||
|
||||
func OwnerIdDomainQuotaKeys(ownerId mcclient.IIdentityProvider) SBaseDomainQuotaKeys {
|
||||
return SBaseDomainQuotaKeys{DomainId: ownerId.GetProjectDomainId()}
|
||||
}
|
||||
|
||||
type TQuotaKeysRelation string
|
||||
|
||||
@@ -26,8 +26,10 @@ func TestRelation(t *testing.T) {
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -36,8 +38,10 @@ func TestRelation(t *testing.T) {
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain2",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -46,8 +50,10 @@ func TestRelation(t *testing.T) {
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
},
|
||||
ProjectId: "project1",
|
||||
},
|
||||
},
|
||||
@@ -57,8 +63,10 @@ func TestRelation(t *testing.T) {
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
},
|
||||
ProjectId: "project2",
|
||||
},
|
||||
},
|
||||
@@ -68,8 +76,10 @@ func TestRelation(t *testing.T) {
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain2",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain2",
|
||||
},
|
||||
ProjectId: "project1",
|
||||
},
|
||||
},
|
||||
@@ -79,35 +89,47 @@ func TestRelation(t *testing.T) {
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
},
|
||||
ProjectId: "project1",
|
||||
},
|
||||
},
|
||||
RegionId: "region1",
|
||||
SRegionalBaseKeys: SRegionalBaseKeys{
|
||||
RegionId: "region1",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Project11Region2 :=
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
},
|
||||
ProjectId: "project1",
|
||||
},
|
||||
},
|
||||
RegionId: "region2",
|
||||
SRegionalBaseKeys: SRegionalBaseKeys{
|
||||
RegionId: "region2",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Project11Aliyun :=
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
},
|
||||
ProjectId: "project1",
|
||||
},
|
||||
Provider: "Aliyun",
|
||||
SCloudResourceBaseKeys: SCloudResourceBaseKeys{
|
||||
Provider: "Aliyun",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -115,13 +137,19 @@ func TestRelation(t *testing.T) {
|
||||
{
|
||||
SRegionalCloudResourceKeys: SRegionalCloudResourceKeys{
|
||||
SCloudResourceKeys: SCloudResourceKeys{
|
||||
SBaseQuotaKeys: SBaseQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
SBaseProjectQuotaKeys: SBaseProjectQuotaKeys{
|
||||
SBaseDomainQuotaKeys: SBaseDomainQuotaKeys{
|
||||
DomainId: "domain1",
|
||||
},
|
||||
ProjectId: "project1",
|
||||
},
|
||||
Provider: "Aliyun",
|
||||
SCloudResourceBaseKeys: SCloudResourceBaseKeys{
|
||||
Provider: "Aliyun",
|
||||
},
|
||||
},
|
||||
SRegionalBaseKeys: SRegionalBaseKeys{
|
||||
RegionId: "region1",
|
||||
},
|
||||
RegionId: "region1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
func (manager *SQuotaBaseManager) ResourceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeProject
|
||||
return manager.scope
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package quotas
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -82,6 +83,8 @@ func cancelUsage(ctx context.Context, userCred mcclient.TokenCredential, usage I
|
||||
if err != nil {
|
||||
log.Errorf("cancelUsage %s fail: %s", jsonutils.Marshal(usage), err)
|
||||
}
|
||||
log.Infof("cancelUsage %s", jsonutils.Marshal(usage))
|
||||
debug.PrintStack()
|
||||
}
|
||||
|
||||
func GetQuotaCount(ctx context.Context, request IQuota, pendingKeys IQuotaKeys) (int, error) {
|
||||
|
||||
Reference in New Issue
Block a user