feature: allow cascade quota set

This commit is contained in:
Qiu Jian
2019-07-02 09:27:55 +08:00
parent f184e2d8f9
commit 49675fe965
3 changed files with 33 additions and 11 deletions
+1
View File
@@ -63,6 +63,7 @@ func init() {
Tenant string `help:"Tenant name or ID to set quota" json:"tenant,omitempty"`
ProjectDomain string `help:"Domain name or ID to set quota" json:"domain,omitempty"`
Action string `help:"quota set action" choices:"add|reset"`
Cascade bool `help:"cascade set quota so that auto increment domain quota if total project quota exceeds parent domain quota"`
QuotaBaseOptions
}
R(&QuotaSetOptions{}, "quota-set", "Set quota for tenant", func(s *mcclient.ClientSession, args *QuotaSetOptions) error {
+3
View File
@@ -35,6 +35,9 @@ quotas:
type: string
description: 设置配额的方式,可能值为set,add和reset,分别代表设置,增加和重置为初始值
default: set
cascade:
type: boolean
description: 设置项目配额时,如果项目总配额超过域配额,则自动调整域配额
cpu:
type: integer
description: 设置CPU配额,单位为个
+29 -11
View File
@@ -167,15 +167,15 @@ func (manager *SQuotaBaseManager) getQuotaHanlder(ctx context.Context, w http.Re
appsrv.SendJSON(w, body)
}
func FetchSetQuotaScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (mcclient.IIdentityProvider, rbacutils.TRbacScope, error) {
func FetchSetQuotaScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (mcclient.IIdentityProvider, rbacutils.TRbacScope, rbacutils.TRbacScope, error) {
var scope rbacutils.TRbacScope
ownerId, err := db.FetchProjectInfo(ctx, data)
if err != nil {
return nil, scope, err
return nil, scope, scope, err
}
var requestScope rbacutils.TRbacScope
ownerScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), quotaKeywords, policy.PolicyActionUpdate)
if ownerId != nil {
var requestScope rbacutils.TRbacScope
if len(ownerId.GetProjectId()) > 0 {
// project level
scope = rbacutils.ScopeProject
@@ -189,14 +189,15 @@ func FetchSetQuotaScope(ctx context.Context, userCred mcclient.TokenCredential,
scope = rbacutils.ScopeDomain
requestScope = rbacutils.ScopeSystem
}
if requestScope.HigherThan(ownerScope) {
return nil, scope, httperrors.NewForbiddenError("not enough privilleges")
}
} else {
ownerId = userCred
scope = rbacutils.ScopeProject
requestScope = rbacutils.ScopeDomain
}
return ownerId, scope, nil
if requestScope.HigherThan(ownerScope) {
return nil, scope, scope, httperrors.NewForbiddenError("not enough privilleges")
}
return ownerId, scope, ownerScope, nil
}
func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request) {
@@ -211,7 +212,7 @@ func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.Re
} else if len(domainId) > 0 {
data.Add(jsonutils.NewString(domainId), "project_domain")
}
ownerId, scope, err := FetchSetQuotaScope(ctx, userCred, data)
ownerId, scope, allowScope, err := FetchSetQuotaScope(ctx, userCred, data)
if err != nil {
httperrors.GeneralServerError(w, err)
return
@@ -266,9 +267,26 @@ func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.Re
total.Add(oquota)
err = total.Exceed(quota, domainQuota)
if err != nil {
log.Errorf("project quota exeed domain quota: %s", err)
httperrors.OutOfQuotaError(w, "project quota exeed domain quota")
return
// exeed domain quota
cascade, _ := body.Bool(manager.KeywordPlural(), "cascade")
if !cascade {
log.Errorf("project quota exeed domain quota: %s", err)
httperrors.OutOfQuotaError(w, "project quota exeed domain quota")
return
} else {
if allowScope != rbacutils.ScopeSystem {
httperrors.OutOfQuotaError(w, "project quota exeed domain quota, no previlige to cascade set")
return
} else {
// cascade set domain quota
err = manager.SetQuota(ctx, userCred, rbacutils.ScopeDomain, ownerId, nil, total)
if err != nil {
log.Errorf("cascade set quota fail %s", err)
httperrors.GeneralServerError(w, err)
return
}
}
}
}
} else {
total, err := manager.getDomainTotalQuota(ctx, ownerId.GetProjectDomainId(), nil)