mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-31 01:35:56 +08:00
1. allow replace set quota when action=replace
2. show when the project external resource was fetched
This commit is contained in:
@@ -62,7 +62,7 @@ func init() {
|
||||
type QuotaSetOptions struct {
|
||||
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"`
|
||||
Action string `help:"quota set action" choices:"add|reset|replace"`
|
||||
Cascade bool `help:"cascade set quota so that auto increment domain quota if total project quota exceeds parent domain quota"`
|
||||
QuotaBaseOptions
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ quotas:
|
||||
properties:
|
||||
action:
|
||||
type: string
|
||||
description: 设置配额的方式,可能值为set,add和reset,分别代表设置,增加和重置为初始值
|
||||
description: 设置配额的方式,可能值为set,replace, add和reset,分别代表设置配额,替换配额,增加配额和重置为初始配额四种方式
|
||||
default: set
|
||||
cascade:
|
||||
type: boolean
|
||||
|
||||
@@ -37,8 +37,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
QUOTA_ACTION_ADD = "add"
|
||||
QUOTA_ACTION_RESET = "reset"
|
||||
QUOTA_ACTION_ADD = "add"
|
||||
QUOTA_ACTION_RESET = "reset"
|
||||
QUOTA_ACTION_REPLACE = "replace"
|
||||
)
|
||||
|
||||
func AddQuotaHandler(manager *SQuotaBaseManager, prefix string, app *appsrv.Application) {
|
||||
@@ -244,6 +245,8 @@ func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.Re
|
||||
oquota.Add(quota)
|
||||
case QUOTA_ACTION_RESET:
|
||||
oquota.FetchSystemQuota(scope, ownerId)
|
||||
case QUOTA_ACTION_REPLACE:
|
||||
oquota = quota
|
||||
default:
|
||||
oquota.Update(quota)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
@@ -49,32 +50,39 @@ type SProjectResource struct {
|
||||
ServiceId string `width:"32" charset:"ascii" primary:"true"`
|
||||
Resource string `width:"32" charset:"ascii" primary:"true"`
|
||||
Count int
|
||||
UpdatedAt time.Time `nullable:"true" updated_at:"true"`
|
||||
}
|
||||
|
||||
type sProjectResourceCount struct {
|
||||
Resource string
|
||||
ResCount int
|
||||
Resource string
|
||||
ResCount int
|
||||
LastUpdate time.Time
|
||||
}
|
||||
|
||||
func (manager *SProjectResourceManager) getProjectResource(projId string) (map[string]int, error) {
|
||||
func (manager *SProjectResourceManager) getProjectResource(projId string) (map[string]int, time.Time, error) {
|
||||
resources := manager.Query().SubQuery()
|
||||
q := resources.Query(
|
||||
resources.Field("resource"),
|
||||
sqlchemy.SUM("res_count", resources.Field("count")),
|
||||
sqlchemy.MAX("last_update", resources.Field("updated_at")),
|
||||
)
|
||||
q = q.Filter(sqlchemy.Equals(resources.Field("project_id"), projId))
|
||||
q = q.GroupBy(resources.Field("resource"))
|
||||
resCnts := make([]sProjectResourceCount, 0)
|
||||
err := q.All(&resCnts)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, errors.Wrap(err, "query.All")
|
||||
return nil, time.Time{}, errors.Wrap(err, "query.All")
|
||||
}
|
||||
ret := make(map[string]int)
|
||||
lastUpdate := time.Time{}
|
||||
for i := range resCnts {
|
||||
if resCnts[i].ResCount == 0 {
|
||||
continue
|
||||
}
|
||||
ret[resCnts[i].Resource] = resCnts[i].ResCount
|
||||
if lastUpdate.IsZero() || lastUpdate.Before(resCnts[i].LastUpdate) {
|
||||
lastUpdate = resCnts[i].LastUpdate
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
return ret, lastUpdate, nil
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -29,6 +30,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/identity"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/keystone/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/pinyinutils"
|
||||
)
|
||||
@@ -258,7 +260,7 @@ func (proj *SProject) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if proj.IsAdminProject() {
|
||||
return httperrors.NewForbiddenError("cannot delete system project")
|
||||
}
|
||||
external, _ := proj.getExternalResources()
|
||||
external, _, _ := proj.getExternalResources()
|
||||
if len(external) > 0 {
|
||||
return httperrors.NewNotEmptyError("project contains external resources")
|
||||
}
|
||||
@@ -304,14 +306,20 @@ func projectExtra(proj *SProject, extra *jsonutils.JSONDict) *jsonutils.JSONDict
|
||||
extra.Add(jsonutils.NewInt(int64(grpCnt)), "group_count")
|
||||
usrCnt, _ := proj.GetUserCount()
|
||||
extra.Add(jsonutils.NewInt(int64(usrCnt)), "user_count")
|
||||
external, _ := proj.getExternalResources()
|
||||
external, update, _ := proj.getExternalResources()
|
||||
if len(external) > 0 {
|
||||
extra.Add(jsonutils.Marshal(external), "ext_resources")
|
||||
extra.Add(jsonutils.NewTimeString(update), "ext_resources_last_update")
|
||||
if update.IsZero() {
|
||||
update = time.Now()
|
||||
}
|
||||
nextUpdate := update.Add(time.Duration(options.Options.FetchProjectResourceCountIntervalSeconds) * time.Second)
|
||||
extra.Add(jsonutils.NewTimeString(nextUpdate), "ext_resources_next_update")
|
||||
}
|
||||
return extra
|
||||
}
|
||||
|
||||
func (proj *SProject) getExternalResources() (map[string]int, error) {
|
||||
func (proj *SProject) getExternalResources() (map[string]int, time.Time, error) {
|
||||
return ProjectResourceManager.getProjectResource(proj.Id)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user