mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
clean usages when resource deleted
This commit is contained in:
@@ -244,4 +244,58 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&QuotaListOptions{}, "region-quota-list", "List region quota of domains or projects of a domain", func(s *mcclient.ClientSession, args *QuotaListOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, e := modules.RegionQuotas.GetQuotaList(s, params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printQuotaList(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&QuotaListOptions{}, "zone-quota-list", "List zone quota of domains or projects of a domain", func(s *mcclient.ClientSession, args *QuotaListOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, e := modules.ZoneQuotas.GetQuotaList(s, params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printQuotaList(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&QuotaListOptions{}, "project-quota-list", "List project quota of domains or projects of a domain", func(s *mcclient.ClientSession, args *QuotaListOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, e := modules.ProjectQuotas.GetQuotaList(s, params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printQuotaList(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&QuotaListOptions{}, "image-quota-list", "List image quota of domains or projects of a domain", func(s *mcclient.ClientSession, args *QuotaListOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, e := modules.ImageQuotas.GetQuotaList(s, params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printQuotaList(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type CleanPendingUsageOptions struct {
|
||||
Scope string `help:"scope" choices:"domain|project"`
|
||||
Project string `help:"Tenant name or ID" json:"tenant"`
|
||||
Domain string `help:"Domain name or ID" json:"domain"`
|
||||
}
|
||||
R(&CleanPendingUsageOptions{}, "clean-pending-usage", "Clean pending usage for project or domain", func(s *mcclient.ClientSession, args *CleanPendingUsageOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
log.Debugf("%s", params)
|
||||
_, err := modules.Quotas.DoCleanPendingUsage(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -149,7 +149,10 @@ func ValidateCreateData(manager IModelManager, ctx context.Context, userCred mcc
|
||||
if err := ValueToError(ret[1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ValueToJSONObject(resVal).(*jsonutils.JSONDict), nil
|
||||
retJson := ValueToJSONObject(resVal).(*jsonutils.JSONDict)
|
||||
// preserve the input info not returned by caller
|
||||
data.Update(retJson)
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func ListItemFilter(manager IModelManager, ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
|
||||
@@ -43,6 +43,10 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
var (
|
||||
CancelUsages func(ctx context.Context, userCred mcclient.TokenCredential, usages []IUsage)
|
||||
)
|
||||
|
||||
type DBModelDispatcher struct {
|
||||
modelManager IModelManager
|
||||
}
|
||||
@@ -1539,6 +1543,7 @@ func objectUpdateSpec(dispatcher *DBModelDispatcher, model IModel, modelValue re
|
||||
|
||||
func DeleteModel(ctx context.Context, userCred mcclient.TokenCredential, item IModel) error {
|
||||
// log.Debugf("Ready to delete %s %s %#v", jsonutils.Marshal(item), item, manager)
|
||||
cleanModelUsages(ctx, userCred, item)
|
||||
_, err := Update(item, func() error {
|
||||
return item.MarkDelete()
|
||||
})
|
||||
|
||||
@@ -30,6 +30,11 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type IUsage interface {
|
||||
FetchUsage(ctx context.Context) error
|
||||
IsEmpty() bool
|
||||
}
|
||||
|
||||
type IModelManager interface {
|
||||
lockman.ILockedClass
|
||||
object.IObject
|
||||
@@ -182,6 +187,8 @@ type IModel interface {
|
||||
CustomizedGetDetailsBody(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error)
|
||||
MarkDeletePreventionOn()
|
||||
MarkDeletePreventionOff()
|
||||
|
||||
GetUsages() []IUsage
|
||||
}
|
||||
|
||||
type IResourceModelManager interface {
|
||||
|
||||
@@ -512,8 +512,17 @@ func (model *SModelBase) CustomizeDelete(ctx context.Context, userCred mcclient.
|
||||
return nil
|
||||
}
|
||||
|
||||
func cleanModelUsages(ctx context.Context, userCred mcclient.TokenCredential, model IModel) {
|
||||
usages := model.GetIModel().GetUsages()
|
||||
if CancelUsages != nil && len(usages) > 0 {
|
||||
CancelUsages(ctx, userCred, usages)
|
||||
}
|
||||
}
|
||||
|
||||
func (model *SModelBase) PreDelete(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
// do nothing
|
||||
// clean usage on predelete
|
||||
// clean usage before fakedelete for pending delete models
|
||||
cleanModelUsages(ctx, userCred, model)
|
||||
}
|
||||
|
||||
func (model *SModelBase) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
@@ -552,3 +561,7 @@ func (model *SModelBase) UpdateInContext(ctx context.Context, userCred mcclient.
|
||||
func (model *SModelBase) DeleteInContext(ctx context.Context, userCred mcclient.TokenCredential, ctxObjs []IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SModelBase) GetUsages() []IUsage {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -85,6 +85,17 @@ func AddQuotaHandler(manager *SQuotaBaseManager, prefix string, app *appsrv.Appl
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.setQuotaHanlder), nil, "set_quota_for_project", nil)
|
||||
|
||||
app.AddHandler2("DELETE",
|
||||
fmt.Sprintf("%s/%s", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.cleanPendingUsageHanlder), nil, "clean_pending_usage", nil)
|
||||
|
||||
app.AddHandler2("DELETE",
|
||||
fmt.Sprintf("%s/%s/domains/<domainid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.cleanPendingUsageHanlder), nil, "clean_pending_usage_for_domain", nil)
|
||||
|
||||
app.AddHandler2("DELETE",
|
||||
fmt.Sprintf("%s/%s/projects/<tenantid>", prefix, manager.KeywordPlural()),
|
||||
auth.Authenticate(manager.cleanPendingUsageHanlder), nil, "clean_pending_usage_for_project", nil)
|
||||
/*app.AddHandler2("POST",
|
||||
fmt.Sprintf("%s/%s/<tenantid>/<action>", prefix, _manager.Keyword()),
|
||||
auth.Authenticate(checkQuotaHanlder), nil, "check_quota", nil)*/
|
||||
@@ -230,6 +241,49 @@ func (manager *SQuotaBaseManager) fetchSetQuotaScope(ctx context.Context, userCr
|
||||
return ownerId, scope, ownerScope, nil
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) cleanPendingUsageHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
params, query, _ := appsrv.FetchEnv(ctx, w, r)
|
||||
userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
|
||||
|
||||
var ownerId mcclient.IIdentityProvider
|
||||
var scope rbacutils.TRbacScope
|
||||
var err error
|
||||
|
||||
projectId := params["<tenantid>"]
|
||||
domainId := params["<domainid>"]
|
||||
if len(projectId) > 0 || len(domainId) > 0 {
|
||||
data := jsonutils.NewDict()
|
||||
if len(domainId) > 0 {
|
||||
data.Add(jsonutils.NewString(domainId), "project_domain")
|
||||
} else if len(projectId) > 0 {
|
||||
data.Add(jsonutils.NewString(projectId), "project")
|
||||
}
|
||||
ownerId, scope, err = db.FetchCheckQueryOwnerScope(ctx, userCred, data, manager, policy.PolicyActionGet, true)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
scopeStr, _ := query.GetString("scope")
|
||||
if scopeStr == "project" {
|
||||
scope = rbacutils.ScopeProject
|
||||
} else if scopeStr == "domain" {
|
||||
scope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
scope = rbacutils.ScopeProject
|
||||
}
|
||||
ownerId = userCred
|
||||
}
|
||||
keys := OwnerIdQuotaKeys(scope, ownerId)
|
||||
err = manager.cleanPendingUsage(ctx, userCred, keys)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
return
|
||||
}
|
||||
rbody := jsonutils.NewDict()
|
||||
appsrv.SendJSON(w, rbody)
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) setQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
params, _, body := appsrv.FetchEnv(ctx, w, r)
|
||||
userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
|
||||
|
||||
@@ -18,7 +18,9 @@ import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/object"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
@@ -29,20 +31,24 @@ type IQuotaKeys interface {
|
||||
}
|
||||
|
||||
type IQuota interface {
|
||||
db.IUsage
|
||||
|
||||
GetKeys() IQuotaKeys
|
||||
SetKeys(IQuotaKeys)
|
||||
|
||||
FetchSystemQuota()
|
||||
FetchUsage(ctx context.Context) error
|
||||
// FetchUsage(ctx context.Context) error
|
||||
Update(quota IQuota)
|
||||
Add(quota IQuota)
|
||||
Sub(quota IQuota)
|
||||
Exceed(request IQuota, quota IQuota) error
|
||||
IsEmpty() bool
|
||||
// IsEmpty() bool
|
||||
ToJSON(prefix string) jsonutils.JSONObject
|
||||
}
|
||||
|
||||
type IQuotaStore interface {
|
||||
object.IObject
|
||||
|
||||
GetQuota(ctx context.Context, keys IQuotaKeys, quota IQuota) error
|
||||
GetChildrenQuotas(ctx context.Context, keys IQuotaKeys) ([]IQuota, error)
|
||||
GetParentQuotas(ctx context.Context, keys IQuotaKeys) ([]IQuota, error)
|
||||
@@ -58,5 +64,9 @@ type IQuotaStore interface {
|
||||
type IQuotaManager interface {
|
||||
db.IResourceModelManager
|
||||
|
||||
checkSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error
|
||||
cancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, localUsage IQuota, cancelUsage IQuota) error
|
||||
cancelUsage(ctx context.Context, userCred mcclient.TokenCredential, usage IQuota) error
|
||||
|
||||
FetchIdNames(ctx context.Context, idMap map[string]map[string]string) (map[string]map[string]string, error)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ type SQuotaBaseManager struct {
|
||||
}
|
||||
|
||||
func NewQuotaBaseManager(model interface{}, tableName string, pendingStore IQuotaStore, usageStore IQuotaStore, keyword, keywordPlural string) SQuotaBaseManager {
|
||||
pendingStore.SetVirtualObject(pendingStore)
|
||||
usageStore.SetVirtualObject(usageStore)
|
||||
return SQuotaBaseManager{
|
||||
SResourceBaseManager: db.NewResourceBaseManager(model, tableName, keyword, keywordPlural),
|
||||
pendingStore: pendingStore,
|
||||
@@ -151,13 +153,13 @@ func (manager *SQuotaBaseManager) setQuotaInternal(ctx context.Context, userCred
|
||||
func (manager *SQuotaBaseManager) addQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota) error {
|
||||
keys := diff.GetKeys()
|
||||
quota := manager.newQuota()
|
||||
quota.SetKeys(keys)
|
||||
err := manager.getQuotaByKeys(ctx, keys, quota)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
// insert one
|
||||
quota.SetKeys(keys)
|
||||
} else {
|
||||
return err
|
||||
return errors.Wrap(err, "manager.getQuotaByKeys")
|
||||
}
|
||||
}
|
||||
quota.Add(diff)
|
||||
@@ -167,13 +169,13 @@ func (manager *SQuotaBaseManager) addQuotaInternal(ctx context.Context, userCred
|
||||
func (manager *SQuotaBaseManager) subQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota) error {
|
||||
keys := diff.GetKeys()
|
||||
quota := manager.newQuota()
|
||||
quota.SetKeys(keys)
|
||||
err := manager.getQuotaByKeys(ctx, keys, quota)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
// insert one
|
||||
quota.SetKeys(keys)
|
||||
} else {
|
||||
return err
|
||||
return errors.Wrap(err, "manager.getQuotaByKeys")
|
||||
}
|
||||
}
|
||||
quota.Sub(diff)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -38,7 +39,28 @@ func (manager *SQuotaBaseManager) newQuota() IQuota {
|
||||
return model.(IQuota)
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) CancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, localUsage IQuota, cancelUsage IQuota) error {
|
||||
func (manager *SQuotaBaseManager) cleanPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error {
|
||||
LockQuotaKeys(ctx, manager, keys)
|
||||
defer ReleaseQuotaKeys(ctx, manager, keys)
|
||||
|
||||
return manager._cleanPendingUsage(ctx, userCred, keys)
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) _cleanPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, keys IQuotaKeys) error {
|
||||
pendings, err := manager.pendingStore.GetChildrenQuotas(ctx, keys)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "manager.pendingStore.GetChildrenQuotas")
|
||||
}
|
||||
for i := range pendings {
|
||||
err := manager.pendingStore.SubQuota(ctx, userCred, pendings[i])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "manager.pendingStore.SubQuota")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) cancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, localUsage IQuota, cancelUsage IQuota) error {
|
||||
LockQuota(ctx, manager, localUsage)
|
||||
defer ReleaseQuota(ctx, manager, localUsage)
|
||||
|
||||
@@ -52,6 +74,7 @@ func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userC
|
||||
pendingUsage := manager.newQuota()
|
||||
pendingUsage.SetKeys(originKeys)
|
||||
pendingUsage.Update(cancelUsage)
|
||||
log.Debugf("pending delete key %s %s", QuotaKeyString(originKeys), jsonutils.Marshal(pendingUsage))
|
||||
err := manager.pendingStore.SubQuota(ctx, userCred, pendingUsage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "manager.pendingStore.SubQuota")
|
||||
@@ -63,6 +86,9 @@ func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userC
|
||||
if localUsage != nil {
|
||||
localUsage.Sub(cancelUsage)
|
||||
}
|
||||
|
||||
log.Debugf("cancelUsage: %s localUsage: %s", jsonutils.Marshal(cancelUsage), jsonutils.Marshal(localUsage))
|
||||
|
||||
// update usages
|
||||
quotas, err := manager.usageStore.GetParentQuotas(ctx, currentKeys)
|
||||
if err != nil {
|
||||
@@ -78,6 +104,30 @@ func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userC
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) cancelUsage(ctx context.Context, userCred mcclient.TokenCredential, usage IQuota) error {
|
||||
LockQuota(ctx, manager, usage)
|
||||
defer ReleaseQuota(ctx, manager, usage)
|
||||
|
||||
return manager._cancelUsage(ctx, userCred, usage)
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) _cancelUsage(ctx context.Context, userCred mcclient.TokenCredential, usage IQuota) error {
|
||||
usages, err := manager.usageStore.GetParentQuotas(ctx, usage.GetKeys())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "manager.usageStore.GetParentQuotas")
|
||||
}
|
||||
subUsage := manager.newQuota()
|
||||
subUsage.Update(usage)
|
||||
for i := range usages {
|
||||
subUsage.SetKeys(usages[i].GetKeys())
|
||||
err := manager.usageStore.SubQuota(ctx, userCred, subUsage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "manager.usageStore.AddQuota")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*func (manager *SQuotaBaseManager) GetPendingUsage(ctx context.Context, keys SQuotaKeys, quota IQuota) error {
|
||||
return manager.pendingStore.GetQuota(ctx, keys, quota)
|
||||
}*/
|
||||
@@ -145,7 +195,7 @@ func (manager *SQuotaBaseManager) DeleteAllQuotas(ctx context.Context, userCred
|
||||
return manager.deleteAllQuotas(ctx, userCred, keys)
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) CheckQuota(ctx context.Context, request IQuota) error {
|
||||
func (manager *SQuotaBaseManager) checkQuota(ctx context.Context, request IQuota) error {
|
||||
LockQuota(ctx, manager, request)
|
||||
defer ReleaseQuota(ctx, manager, request)
|
||||
|
||||
@@ -182,7 +232,7 @@ func (manager *SQuotaBaseManager) _checkQuota(ctx context.Context, request IQuot
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SQuotaBaseManager) CheckSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error {
|
||||
func (manager *SQuotaBaseManager) checkSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error {
|
||||
LockQuota(ctx, manager, quota)
|
||||
defer ReleaseQuota(ctx, manager, quota)
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// 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 quotas
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
var (
|
||||
quotaManagerTable map[reflect.Type]IQuotaManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
quotaManagerTable = make(map[reflect.Type]IQuotaManager)
|
||||
|
||||
db.CancelUsages = CancelUsages
|
||||
}
|
||||
|
||||
func Register(manager IQuotaManager) {
|
||||
obj, _ := db.NewModelObject(manager)
|
||||
ele := reflect.Indirect(reflect.ValueOf(obj))
|
||||
quotaManagerTable[ele.Type()] = manager
|
||||
manager.SetVirtualObject(manager)
|
||||
}
|
||||
|
||||
func getQuotaManager(quota IQuota) IQuotaManager {
|
||||
quotaType := reflect.Indirect(reflect.ValueOf(quota)).Type()
|
||||
if m, ok := quotaManagerTable[quotaType]; ok {
|
||||
return m
|
||||
} else {
|
||||
log.Fatalf("No manager for quota %s", quotaType.Name())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func CancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, localUsage IQuota, cancelUsage IQuota) error {
|
||||
manager := getQuotaManager(cancelUsage)
|
||||
return manager.cancelPendingUsage(ctx, userCred, localUsage, cancelUsage)
|
||||
}
|
||||
|
||||
func CheckSetPendingQuota(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error {
|
||||
manager := getQuotaManager(quota)
|
||||
return manager.checkSetPendingQuota(ctx, userCred, quota)
|
||||
}
|
||||
|
||||
func CancelUsages(ctx context.Context, userCred mcclient.TokenCredential, usages []db.IUsage) {
|
||||
for _, usage := range usages {
|
||||
cancelUsage(ctx, userCred, usage.(IQuota))
|
||||
}
|
||||
}
|
||||
|
||||
func cancelUsage(ctx context.Context, userCred mcclient.TokenCredential, usage IQuota) {
|
||||
manager := getQuotaManager(usage)
|
||||
err := manager.cancelUsage(ctx, userCred, usage)
|
||||
if err != nil {
|
||||
log.Errorf("cancelUsage %s fail: %s", jsonutils.Marshal(usage), err)
|
||||
}
|
||||
}
|
||||
@@ -436,7 +436,7 @@ func (model *SVirtualResourceBase) Delete(ctx context.Context, userCred mcclient
|
||||
if !model.PendingDeleted {
|
||||
model.DoPendingDelete(ctx, userCred)
|
||||
}
|
||||
return DeleteModel(ctx, userCred, model)
|
||||
return DeleteModel(ctx, userCred, model.GetIVirtualModel())
|
||||
}
|
||||
|
||||
func (model *SVirtualResourceBase) AllowPerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
|
||||
@@ -426,7 +426,7 @@ func (manager *SBucketManager) ValidateCreateData(
|
||||
managerV.Model.(*SCloudprovider))
|
||||
pendingUsage := SRegionQuota{Bucket: 1}
|
||||
pendingUsage.SetKeys(quotaKeys)
|
||||
if err := RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
if err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
return input, httperrors.NewOutOfQuotaError("%s", err)
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ func (bucket *SBucket) PostCreate(
|
||||
log.Errorf("bucket.GetQuotaKeys fail %s", err)
|
||||
} else {
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
if err != nil {
|
||||
log.Errorf("CancelPendingUsage error %s", err)
|
||||
}
|
||||
@@ -761,7 +761,7 @@ func (bucket *SBucket) PerformMakedir(
|
||||
return nil, httperrors.NewInternalServerError("bucket.GetQuotaKeys %s", err)
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
if err := RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
if err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("%s", err)
|
||||
}
|
||||
|
||||
@@ -775,7 +775,7 @@ func (bucket *SBucket) PerformMakedir(
|
||||
|
||||
bucket.syncWithCloudBucket(ctx, userCred, iBucket, nil, true)
|
||||
|
||||
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -930,7 +930,7 @@ func (bucket *SBucket) PerformUpload(
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
if !pendingUsage.IsEmpty() {
|
||||
if err := RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
if err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("%s", err)
|
||||
}
|
||||
}
|
||||
@@ -946,7 +946,7 @@ func (bucket *SBucket) PerformUpload(
|
||||
bucket.syncWithCloudBucket(ctx, userCred, iBucket, nil, true)
|
||||
|
||||
if !pendingUsage.IsEmpty() {
|
||||
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
@@ -1251,3 +1251,19 @@ func (bucket *SBucket) GetDetailsAccessInfo(
|
||||
info.(*jsonutils.JSONDict).Add(jsonutils.NewString(account.Brand), "PROVIDER")
|
||||
return info, err
|
||||
}
|
||||
|
||||
func (bucket *SBucket) GetUsages() []db.IUsage {
|
||||
if bucket.PendingDeleted || bucket.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SRegionQuota{Bucket: 1}
|
||||
keys, err := bucket.GetQuotaKeys()
|
||||
if err != nil {
|
||||
log.Errorf("bucket.GetQuotaKeys fail %s", err)
|
||||
return nil
|
||||
}
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -1388,3 +1389,24 @@ func (man *SDBInstanceManager) TotalCount(
|
||||
q = rangeObjectsFilter(q, rangeObjs, q.Field("cloudregion_id"), nil, q.Field("manager_id"))
|
||||
return q.CountWithError()
|
||||
}
|
||||
|
||||
func (dbinstance *SDBInstance) GetQuotaKeys() quotas.IQuotaKeys {
|
||||
return fetchRegionalQuotaKeys(
|
||||
rbacutils.ScopeProject,
|
||||
dbinstance.GetOwnerId(),
|
||||
dbinstance.GetRegion(),
|
||||
dbinstance.GetCloudprovider(),
|
||||
)
|
||||
}
|
||||
|
||||
func (dbinstance *SDBInstance) GetUsages() []db.IUsage {
|
||||
if dbinstance.PendingDeleted || dbinstance.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SRegionQuota{Rds: 1}
|
||||
keys := dbinstance.GetQuotaKeys()
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +507,7 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
|
||||
pendingUsage := SQuota{Storage: diskConfig.SizeMb}
|
||||
pendingUsage.SetKeys(quotaKey)
|
||||
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
if err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("%s", err)
|
||||
}
|
||||
return input.JSON(input), nil
|
||||
@@ -919,7 +919,7 @@ func (disk *SDisk) doResize(ctx context.Context, userCred mcclient.TokenCredenti
|
||||
return httperrors.NewInternalServerError("disk.GetQuotaKeys fail %s", err)
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
|
||||
if err != nil {
|
||||
return httperrors.NewGeneralError(err)
|
||||
}
|
||||
@@ -2434,3 +2434,19 @@ func (self *SDisk) PerformChangeOwner(ctx context.Context, userCred mcclient.Tok
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (disk *SDisk) GetUsages() []db.IUsage {
|
||||
if disk.PendingDeleted || disk.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SQuota{Storage: disk.DiskSize}
|
||||
keys, err := disk.GetQuotaKeys()
|
||||
if err != nil {
|
||||
log.Errorf("disk.GetQuotaKeys fail %s", err)
|
||||
return nil
|
||||
}
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
@@ -1266,3 +1267,24 @@ func (man *SElasticcacheManager) TotalCount(
|
||||
q = rangeObjectsFilter(q, rangeObjs, q.Field("cloudregion_id"), nil, q.Field("manager_id"))
|
||||
return q.CountWithError()
|
||||
}
|
||||
|
||||
func (cache *SElasticcache) GetQuotaKeys() quotas.IQuotaKeys {
|
||||
return fetchRegionalQuotaKeys(
|
||||
rbacutils.ScopeProject,
|
||||
cache.GetOwnerId(),
|
||||
cache.GetRegion(),
|
||||
cache.GetCloudprovider(),
|
||||
)
|
||||
}
|
||||
|
||||
func (cache *SElasticcache) GetUsages() []db.IUsage {
|
||||
if cache.PendingDeleted || cache.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SRegionQuota{Cache: 1}
|
||||
keys := cache.GetQuotaKeys()
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,7 +723,7 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr
|
||||
eipPendingUsage := &SRegionQuota{Eip: 1}
|
||||
quotaKeys := fetchRegionalQuotaKeys(rbacutils.ScopeProject, ownerId, region, provider)
|
||||
eipPendingUsage.SetKeys(quotaKeys)
|
||||
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, eipPendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, eipPendingUsage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -753,7 +753,7 @@ func (self *SElasticip) PostCreate(ctx context.Context, userCred mcclient.TokenC
|
||||
log.Errorf("GetQuotaKeys fail %s", err)
|
||||
} else {
|
||||
eipPendingUsage.SetKeys(keys)
|
||||
err := RegionQuotaManager.CancelPendingUsage(ctx, userCred, eipPendingUsage, eipPendingUsage)
|
||||
err := quotas.CancelPendingUsage(ctx, userCred, eipPendingUsage, eipPendingUsage)
|
||||
if err != nil {
|
||||
log.Errorf("SElasticip CancelPendingUsage error: %s", err)
|
||||
}
|
||||
@@ -1103,7 +1103,7 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
|
||||
host.GetCloudprovider(),
|
||||
)
|
||||
eipPendingUsage.SetKeys(keys)
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, eipPendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, pendingUsage, eipPendingUsage)
|
||||
|
||||
return &eip, nil
|
||||
}
|
||||
@@ -1294,3 +1294,19 @@ func (self *SElasticip) getCloudProviderInfo() SCloudProviderInfo {
|
||||
provider := self.GetCloudprovider()
|
||||
return MakeCloudProviderInfo(region, nil, provider)
|
||||
}
|
||||
|
||||
func (eip *SElasticip) GetUsages() []db.IUsage {
|
||||
if eip.PendingDeleted || eip.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SRegionQuota{Eip: 1}
|
||||
keys, err := eip.GetQuotaKeys()
|
||||
if err != nil {
|
||||
log.Errorf("disk.GetQuotaKeys fail %s", err)
|
||||
return nil
|
||||
}
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1533,7 +1533,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
return nil, err
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, err.Error(), userCred, false)
|
||||
return nil, httperrors.NewOutOfQuotaError(err.Error())
|
||||
@@ -1544,7 +1544,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
|
||||
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage, false, false, nil, nil, false)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage)
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, err.Error(), userCred, false)
|
||||
return nil, httperrors.NewBadRequestError(err.Error())
|
||||
}
|
||||
@@ -2109,14 +2109,14 @@ func (self *SGuest) PerformAttachnetwork(ctx context.Context, userCred mcclient.
|
||||
return nil, err
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError(err.Error())
|
||||
}
|
||||
host := self.GetHost()
|
||||
_, err = self.attach2NetworkDesc(ctx, userCred, host, conf, pendingUsage, nil)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage)
|
||||
return nil, httperrors.NewBadRequestError(err.Error())
|
||||
}
|
||||
host.ClearSchedDescCache()
|
||||
@@ -2396,7 +2396,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
if !pendingUsage.IsEmpty() {
|
||||
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
err := quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2405,7 +2405,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
if len(newDisks) > 0 {
|
||||
err := self.CreateDisksOnHost(ctx, userCred, host, newDisks, pendingUsage, false, false, nil, nil, false)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage)
|
||||
return nil, httperrors.NewBadRequestError("Create disk on host error: %s", err)
|
||||
}
|
||||
confs.Add(jsonutils.Marshal(newDisks), "create")
|
||||
@@ -2871,7 +2871,7 @@ func (self *SGuest) PerformCreateEip(ctx context.Context, userCred mcclient.Toke
|
||||
return nil, err
|
||||
}
|
||||
eipPendingUsage.SetKeys(keys)
|
||||
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, eipPendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, eipPendingUsage)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("Out of eip quota: %s", err)
|
||||
}
|
||||
@@ -3226,7 +3226,7 @@ func (self *SGuest) PerformCreateBackup(ctx context.Context, userCred mcclient.T
|
||||
return nil, err
|
||||
}
|
||||
req.SetKeys(keys)
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, &req)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, &req)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError(err.Error())
|
||||
}
|
||||
@@ -3235,7 +3235,7 @@ func (self *SGuest) PerformCreateBackup(ctx context.Context, userCred mcclient.T
|
||||
params.Set("guest_status", jsonutils.NewString(self.Status))
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestCreateBackupTask", self, userCred, params, "", "", &req)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &req, &req)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &req, &req)
|
||||
log.Errorln(err)
|
||||
return nil, err
|
||||
} else {
|
||||
@@ -4128,7 +4128,7 @@ func (self *SGuest) validateCreateInstanceSnapshot(
|
||||
return nil, err
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
|
||||
}
|
||||
@@ -4151,13 +4151,13 @@ func (self *SGuest) PerformInstanceSnapshot(
|
||||
name, _ := data.GetString("name")
|
||||
instanceSnapshot, err := InstanceSnapshotManager.CreateInstanceSnapshot(ctx, ownerId, self, name, false)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(
|
||||
quotas.CancelPendingUsage(
|
||||
ctx, userCred, pendingUsage, pendingUsage)
|
||||
return nil, httperrors.NewInternalServerError("create instance snapshot failed: %s", err)
|
||||
}
|
||||
err = self.InstaceCreateSnapshot(ctx, userCred, ownerId, instanceSnapshot, pendingUsage)
|
||||
if err != nil {
|
||||
RegionQuotaManager.CancelPendingUsage(
|
||||
quotas.CancelPendingUsage(
|
||||
ctx, userCred, pendingUsage, pendingUsage)
|
||||
return nil, httperrors.NewInternalServerError("start create snapshot task failed: %s", err)
|
||||
}
|
||||
@@ -4257,24 +4257,24 @@ func (self *SGuest) PerformSnapshotAndClone(
|
||||
pendingUsage, pendingRegionUsage, err := self.getGuestUsage(int(count))
|
||||
keys, err := self.GetQuotaKeys()
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage)
|
||||
return nil, err
|
||||
}
|
||||
pendingUsage.SetKeys(keys)
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, snapshotUsage, snapshotUsage)
|
||||
return nil, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
|
||||
}
|
||||
regionKeys, err := self.GetRegionalQuotaKeys()
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
return nil, err
|
||||
}
|
||||
pendingRegionUsage.SetKeys(regionKeys)
|
||||
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingRegionUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, &pendingRegionUsage)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
return nil, err
|
||||
}
|
||||
pendingRegionUsage.Snapshot = snapshotUsage.Snapshot
|
||||
@@ -4282,24 +4282,24 @@ func (self *SGuest) PerformSnapshotAndClone(
|
||||
instanceSnapshotName, err := db.GenerateName(InstanceSnapshotManager, self.GetOwnerId(),
|
||||
fmt.Sprintf("%s-%s", newlyGuestName, rand.String(8)))
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
return nil, httperrors.NewInternalServerError("Generate snapshot name failed %s", err)
|
||||
}
|
||||
instanceSnapshot, err := InstanceSnapshotManager.CreateInstanceSnapshot(
|
||||
ctx, self.GetOwnerId(), self, instanceSnapshotName,
|
||||
jsonutils.QueryBoolean(data, "auto_delete_instance_snapshot", false))
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
return nil, httperrors.NewInternalServerError("create instance snapshot failed: %s", err)
|
||||
}
|
||||
|
||||
err = self.StartInstanceSnapshotAndCloneTask(
|
||||
ctx, userCred, newlyGuestName, &pendingUsage, &pendingRegionUsage, instanceSnapshot, data.(*jsonutils.JSONDict))
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
RegionQuotaManager.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
// errors_aggr "yunion.io/x/pkg/util/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
@@ -831,10 +830,13 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
|
||||
if vcpuCount > 0 || vmemSize > 0 {
|
||||
err = self.checkUpdateQuota(ctx, userCred, vcpuCount, vmemSize)
|
||||
quota, err := self.checkUpdateQuota(ctx, userCred, vcpuCount, vmemSize)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError(err.Error())
|
||||
}
|
||||
if !quota.IsEmpty() {
|
||||
data.Add(jsonutils.Marshal(quota), "pending_usage")
|
||||
}
|
||||
}
|
||||
|
||||
if data.Contains("name") {
|
||||
@@ -908,8 +910,8 @@ func (manager *SGuestManager) BatchPreValidate(
|
||||
quota.SetKeys(keys)
|
||||
regionQuota.SetKeys(regionKeys)
|
||||
return func() {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, quota, quota)
|
||||
RegionQuotaManager.CancelPendingUsage(ctx, userCred, regionQuota, regionQuota)
|
||||
quotas.CancelPendingUsage(ctx, userCred, quota, quota)
|
||||
quotas.CancelPendingUsage(ctx, userCred, regionQuota, regionQuota)
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
@@ -1356,6 +1358,13 @@ func (manager *SGuestManager) validateEip(userCred mcclient.TokenCredential, inp
|
||||
|
||||
func (self *SGuest) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SVirtualResourceBase.PostUpdate(ctx, userCred, query, data)
|
||||
|
||||
if data.Contains("pending_usage") {
|
||||
quota := SQuota{}
|
||||
data.Unmarshal("a, "pending_usage")
|
||||
quotas.CancelPendingUsage(ctx, userCred, "a, "a)
|
||||
}
|
||||
|
||||
self.StartSyncTask(ctx, userCred, true, "")
|
||||
}
|
||||
|
||||
@@ -1368,18 +1377,18 @@ func (manager *SGuestManager) checkCreateQuota(
|
||||
count int,
|
||||
) (*SQuota, *SRegionQuota, error) {
|
||||
req, regionReq := getGuestResourceRequirements(ctx, userCred, input, ownerId, count, hasBackup)
|
||||
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, &req)
|
||||
err := quotas.CheckSetPendingQuota(ctx, userCred, &req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = RegionQuotaManager.CheckSetPendingQuota(ctx, userCred, ®ionReq)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, ®ionReq)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return &req, ®ionReq, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) checkUpdateQuota(ctx context.Context, userCred mcclient.TokenCredential, vcpuCount int, vmemSize int) error {
|
||||
func (self *SGuest) checkUpdateQuota(ctx context.Context, userCred mcclient.TokenCredential, vcpuCount int, vmemSize int) (quotas.IQuota, error) {
|
||||
req := SQuota{}
|
||||
|
||||
if vcpuCount > 0 && vcpuCount > int(self.VcpuCount) {
|
||||
@@ -1392,12 +1401,15 @@ func (self *SGuest) checkUpdateQuota(ctx context.Context, userCred mcclient.Toke
|
||||
|
||||
keys, err := self.GetQuotaKeys()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "self.GetQuotaKeys")
|
||||
return nil, errors.Wrap(err, "self.GetQuotaKeys")
|
||||
}
|
||||
req.SetKeys(keys)
|
||||
err = QuotaManager.CheckQuota(ctx, &req)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, &req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "quotas.CheckSetPendingQuota")
|
||||
}
|
||||
|
||||
return err
|
||||
return &req, nil
|
||||
}
|
||||
|
||||
func getGuestResourceRequirements(
|
||||
@@ -1471,6 +1483,7 @@ func getGuestResourceRequirements(
|
||||
func (guest *SGuest) getGuestBackupResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential) SQuota {
|
||||
guestDisksSize := guest.getDiskSize()
|
||||
return SQuota{
|
||||
Count: 1,
|
||||
Cpu: int(guest.VcpuCount),
|
||||
Memory: guest.VmemSize,
|
||||
Storage: guestDisksSize,
|
||||
@@ -2562,7 +2575,7 @@ func (self *SGuest) attach2NetworkOnce(ctx context.Context, userCred mcclient.To
|
||||
log.Warningf("self.GetRegionalQuotaKeys fail %s", err)
|
||||
}
|
||||
cancelUsage.SetKeys(keys)
|
||||
err = RegionQuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
|
||||
if err != nil {
|
||||
log.Warningf("QuotaManager.CancelPendingUsage fail %s", err)
|
||||
}
|
||||
@@ -3162,7 +3175,7 @@ func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.T
|
||||
return nil, err
|
||||
}
|
||||
cancelUsage.SetKeys(keys)
|
||||
err = QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
|
||||
|
||||
return disk, nil
|
||||
}
|
||||
@@ -3251,7 +3264,7 @@ func (self *SGuest) createIsolatedDeviceOnHost(ctx context.Context, userCred mcc
|
||||
return err
|
||||
}
|
||||
cancelUsage.SetKeys(keys)
|
||||
err = QuotaManager.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4899,6 +4912,7 @@ func (self *SGuest) GetDiskSnapshotsNotInInstanceSnapshots() ([]SSnapshot, error
|
||||
func (self *SGuest) getGuestUsage(guestCount int) (SQuota, SRegionQuota, error) {
|
||||
usage := SQuota{}
|
||||
regionUsage := SRegionQuota{}
|
||||
usage.Count = guestCount
|
||||
usage.Cpu = int(self.VcpuCount) * guestCount
|
||||
usage.Memory = int(self.VmemSize * guestCount)
|
||||
diskSize := self.getDiskSize()
|
||||
@@ -5030,3 +5044,25 @@ func (guest *SGuest) GetQuotaKeys() (quotas.IQuotaKeys, error) {
|
||||
hypervisor,
|
||||
), nil
|
||||
}
|
||||
|
||||
func (guest *SGuest) GetUsages() []db.IUsage {
|
||||
if guest.PendingDeleted || guest.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage, regionUsage, err := guest.getGuestUsage(1)
|
||||
if err != nil {
|
||||
log.Errorf("guest.getGuestUsage fail %s", err)
|
||||
return nil
|
||||
}
|
||||
keys, err := guest.GetQuotaKeys()
|
||||
if err != nil {
|
||||
log.Errorf("guest.GetQuotaKeys fail %s", err)
|
||||
return nil
|
||||
}
|
||||
usage.SetKeys(keys)
|
||||
regionUsage.SetKeys(keys.(SComputeResourceKeys).SRegionalCloudResourceKeys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
®ionUsage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -883,3 +884,24 @@ func (man *SLoadbalancerManager) TotalCount(
|
||||
q = rangeObjectsFilter(q, rangeObjs, nil, q.Field("zone_id"), q.Field("manager_id"))
|
||||
return q.CountWithError()
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetQuotaKeys() quotas.IQuotaKeys {
|
||||
return fetchZonalQuotaKeys(
|
||||
rbacutils.ScopeProject,
|
||||
lb.GetOwnerId(),
|
||||
lb.GetZone(),
|
||||
lb.GetCloudprovider(),
|
||||
)
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) GetUsages() []db.IUsage {
|
||||
if lb.PendingDeleted || lb.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SZoneQuota{Loadbalancer: 1}
|
||||
keys := lb.GetQuotaKeys()
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ func init() {
|
||||
"project_quota_usages",
|
||||
),
|
||||
}
|
||||
ProjectUsageManager.SetVirtualObject(ProjectUsageManager)
|
||||
ProjectPendingUsageManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaUsageManager(ProjectQuota,
|
||||
"project_quota_pending_usage_tbl",
|
||||
@@ -52,7 +51,6 @@ func init() {
|
||||
"project_quota_pending_usages",
|
||||
),
|
||||
}
|
||||
ProjectPendingUsageManager.SetVirtualObject(ProjectPendingUsageManager)
|
||||
ProjectQuotaManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaBaseManager(ProjectQuota,
|
||||
"project_quota_tbl",
|
||||
@@ -62,7 +60,7 @@ func init() {
|
||||
"project_quotas",
|
||||
),
|
||||
}
|
||||
ProjectQuotaManager.SetVirtualObject(ProjectQuotaManager)
|
||||
quotas.Register(ProjectQuotaManager)
|
||||
}
|
||||
|
||||
type SProjectQuota struct {
|
||||
|
||||
@@ -57,7 +57,6 @@ func init() {
|
||||
"quota_usages",
|
||||
),
|
||||
}
|
||||
QuotaUsageManager.SetVirtualObject(QuotaUsageManager)
|
||||
QuotaPendingUsageManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaUsageManager(Quota,
|
||||
"quota_pending_usage_tbl",
|
||||
@@ -65,7 +64,6 @@ func init() {
|
||||
"quota_pending_usages",
|
||||
),
|
||||
}
|
||||
QuotaPendingUsageManager.SetVirtualObject(QuotaPendingUsageManager)
|
||||
QuotaManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaBaseManager(Quota,
|
||||
"quota_tbl",
|
||||
@@ -75,7 +73,7 @@ func init() {
|
||||
"quotas",
|
||||
),
|
||||
}
|
||||
QuotaManager.SetVirtualObject(QuotaManager)
|
||||
quotas.Register(QuotaManager)
|
||||
}
|
||||
|
||||
type SQuota struct {
|
||||
|
||||
@@ -46,7 +46,6 @@ func init() {
|
||||
"region_quota_usages",
|
||||
),
|
||||
}
|
||||
RegionUsageManager.SetVirtualObject(RegionUsageManager)
|
||||
RegionPendingUsageManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaUsageManager(RegionQuota,
|
||||
"region_quota_pending_usage_tbl",
|
||||
@@ -54,7 +53,6 @@ func init() {
|
||||
"region_quota_pending_usages",
|
||||
),
|
||||
}
|
||||
RegionPendingUsageManager.SetVirtualObject(RegionPendingUsageManager)
|
||||
RegionQuotaManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaBaseManager(RegionQuota,
|
||||
"region_quota_tbl",
|
||||
@@ -64,7 +62,7 @@ func init() {
|
||||
"region_quotas",
|
||||
),
|
||||
}
|
||||
RegionQuotaManager.SetVirtualObject(RegionQuotaManager)
|
||||
quotas.Register(RegionQuotaManager)
|
||||
}
|
||||
|
||||
type SRegionQuota struct {
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -865,3 +866,21 @@ func (self *SSecurityGroup) RealDelete(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
return self.SVirtualResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (sg *SSecurityGroup) GetQuotaKeys() quotas.IQuotaKeys {
|
||||
return quotas.OwnerIdQuotaKeys(rbacutils.ScopeProject,
|
||||
sg.GetOwnerId(),
|
||||
)
|
||||
}
|
||||
|
||||
func (sg *SSecurityGroup) GetUsages() []db.IUsage {
|
||||
if sg.PendingDeleted || sg.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SProjectQuota{Secgroup: 1}
|
||||
keys := sg.GetQuotaKeys()
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -268,7 +269,7 @@ func (manager *SSnapshotManager) ValidateCreateData(
|
||||
return input, err
|
||||
}
|
||||
pendingUsage.SetKeys(keys.(SComputeResourceKeys).SRegionalCloudResourceKeys)
|
||||
err = QuotaManager.CheckQuota(ctx, pendingUsage)
|
||||
err = quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
@@ -280,6 +281,18 @@ func (self *SSnapshot) CustomizeCreate(ctx context.Context, userCred mcclient.To
|
||||
return self.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (snapshot *SSnapshot) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
snapshot.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
|
||||
pendingUsage := SRegionQuota{Snapshot: 1}
|
||||
keys := snapshot.GetQuotaKeys()
|
||||
pendingUsage.SetKeys(keys)
|
||||
err := quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
if err != nil {
|
||||
log.Errorf("quotas.CancelPendingUsage fail %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SSnapshotManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
snapshot := items[0].(*SSnapshot)
|
||||
snapshot.StartSnapshotCreateTask(ctx, userCred, nil, "")
|
||||
@@ -900,3 +913,24 @@ func (manager *SSnapshotManager) StartSnapshotCleanupTask(
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (snapshot *SSnapshot) GetQuotaKeys() quotas.IQuotaKeys {
|
||||
return fetchRegionalQuotaKeys(
|
||||
rbacutils.ScopeProject,
|
||||
snapshot.GetOwnerId(),
|
||||
snapshot.GetRegion(),
|
||||
snapshot.GetCloudprovider(),
|
||||
)
|
||||
}
|
||||
|
||||
func (snapshot *SSnapshot) GetUsages() []db.IUsage {
|
||||
if snapshot.PendingDeleted || snapshot.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SRegionQuota{Snapshot: 1}
|
||||
keys := snapshot.GetQuotaKeys()
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ func init() {
|
||||
"zone_quota_usages",
|
||||
),
|
||||
}
|
||||
ZoneUsageManager.SetVirtualObject(ZoneUsageManager)
|
||||
ZonePendingUsageManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaUsageManager(ZoneQuota,
|
||||
"zone_quota_pending_usage_tbl",
|
||||
@@ -54,7 +53,6 @@ func init() {
|
||||
"zone_quota_pending_usages",
|
||||
),
|
||||
}
|
||||
ZonePendingUsageManager.SetVirtualObject(ZonePendingUsageManager)
|
||||
ZoneQuotaManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaBaseManager(ZoneQuota,
|
||||
"zone_quota_tbl",
|
||||
@@ -64,7 +62,7 @@ func init() {
|
||||
"zone_quotas",
|
||||
),
|
||||
}
|
||||
ZoneQuotaManager.SetVirtualObject(ZoneQuotaManager)
|
||||
quotas.Register(ZoneQuotaManager)
|
||||
}
|
||||
|
||||
type SZoneQuota struct {
|
||||
|
||||
@@ -17,6 +17,7 @@ package tasks
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
@@ -39,7 +40,7 @@ func (self *SDiskBaseTask) finalReleasePendingUsage(ctx context.Context) {
|
||||
pendingUsage := models.SQuota{}
|
||||
err := self.GetPendingUsage(&pendingUsage, 0)
|
||||
if err == nil && !pendingUsage.IsEmpty() {
|
||||
models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -144,7 +145,7 @@ func (self *DiskBatchCreateTask) startCreateDisk(ctx context.Context, disk *mode
|
||||
log.Warningf("disk.GetQuotaKeys fail %s", err)
|
||||
}
|
||||
quotaStorage.SetKeys(keys)
|
||||
models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, "aStorage)
|
||||
quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, "aStorage)
|
||||
self.SetPendingUsage(&pendingUsage, 0)
|
||||
|
||||
disk.StartDiskCreateTask(ctx, self.GetUserCred(), false, "", self.GetTaskId())
|
||||
|
||||
@@ -17,6 +17,7 @@ package tasks
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
@@ -39,11 +40,11 @@ func (self *SGuestBaseTask) finalReleasePendingUsage(ctx context.Context) {
|
||||
pendingUsage := models.SQuota{}
|
||||
err := self.GetPendingUsage(&pendingUsage, 0)
|
||||
if err == nil && !pendingUsage.IsEmpty() {
|
||||
models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
}
|
||||
pendingRegionUsage := models.SRegionQuota{}
|
||||
err = self.GetPendingUsage(&pendingRegionUsage, 1)
|
||||
if err == nil && !pendingRegionUsage.IsEmpty() {
|
||||
models.RegionQuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
quotas.CancelPendingUsage(ctx, self.UserCred, &pendingRegionUsage, &pendingRegionUsage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -82,7 +83,7 @@ func (self *GuestBatchCreateTask) allocateGuestOnHost(ctx context.Context, guest
|
||||
log.Errorf("guest.GetQuotaKeys fail %s", err)
|
||||
}
|
||||
quotaCpuMem.SetKeys(keys)
|
||||
err = models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, "aCpuMem)
|
||||
err = quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, "aCpuMem)
|
||||
self.SetPendingUsage(&pendingUsage, 0)
|
||||
|
||||
input, err := self.GetCreateInput()
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
@@ -234,7 +235,7 @@ func (self *GuestChangeConfigTask) OnGuestChangeCpuMemSpecComplete(ctx context.C
|
||||
lockman.LockClass(ctx, guest.GetModelManager(), guest.ProjectId)
|
||||
defer lockman.ReleaseClass(ctx, guest.GetModelManager(), guest.ProjectId)
|
||||
|
||||
err = models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &cancelUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &cancelUsage)
|
||||
if err != nil {
|
||||
self.markStageFailed(ctx, guest, fmt.Sprintf("CancelPendingUsage fail %s", err))
|
||||
return
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
@@ -67,13 +68,13 @@ func (self *InstanceSnapshotAndCloneTask) finalReleasePendingUsage(ctx context.C
|
||||
pendingUsage := models.SQuota{}
|
||||
err := self.GetPendingUsage(&pendingUsage, 0)
|
||||
if err == nil && !pendingUsage.IsEmpty() {
|
||||
models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
}
|
||||
|
||||
pendingRegionUsage := models.SRegionQuota{}
|
||||
err = self.GetPendingUsage(&pendingRegionUsage, 1)
|
||||
if err == nil && !pendingRegionUsage.IsEmpty() {
|
||||
models.QuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -48,7 +49,7 @@ func (self *InstanceSnapshotCreateTask) finalReleasePendingUsage(ctx context.Con
|
||||
pendingUsage := models.SRegionQuota{}
|
||||
err := self.GetPendingUsage(&pendingUsage, 0)
|
||||
if err == nil && !pendingUsage.IsEmpty() {
|
||||
models.RegionQuotaManager.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &pendingUsage)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
@@ -33,7 +34,7 @@ func ClearTaskPendingUsage(ctx context.Context, task taskman.ITask) error {
|
||||
return errors.Wrap(err, "task.GetPendingUsage")
|
||||
}
|
||||
|
||||
err = models.QuotaManager.CancelPendingUsage(ctx, task.GetUserCred(), &pendingUsage, &pendingUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, task.GetUserCred(), &pendingUsage, &pendingUsage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "models.QuotaManager.CancelPendingUsage")
|
||||
}
|
||||
@@ -57,7 +58,7 @@ func ClearTaskPendingRegionUsage(ctx context.Context, task taskman.ITask) error
|
||||
return errors.Wrap(err, "task.GetPendingUsage")
|
||||
}
|
||||
|
||||
err = models.RegionQuotaManager.CancelPendingUsage(ctx, task.GetUserCred(), &pendingUsage, &pendingUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, task.GetUserCred(), &pendingUsage, &pendingUsage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "models.QuotaManager.CancelPendingUsage")
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ func cancelPendingUsage(ctx context.Context, task IScheduleTask) {
|
||||
return
|
||||
}
|
||||
if !pendingUsage.IsEmpty() {
|
||||
err = models.QuotaManager.CancelPendingUsage(ctx, task.GetUserCred(), &pendingUsage, &pendingUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, task.GetUserCred(), &pendingUsage, &pendingUsage)
|
||||
if err != nil {
|
||||
log.Errorf("cancelpendingusage error %s", err)
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func cancelPendingUsage(ctx context.Context, task IScheduleTask) {
|
||||
return
|
||||
}
|
||||
if !pendingRegionUsage.IsEmpty() {
|
||||
err = models.RegionQuotaManager.CancelPendingUsage(ctx, task.GetUserCred(), &pendingRegionUsage, &pendingRegionUsage)
|
||||
err = quotas.CancelPendingUsage(ctx, task.GetUserCred(), &pendingRegionUsage, &pendingRegionUsage)
|
||||
if err != nil {
|
||||
log.Errorf("cancelpendingusage error %s", err)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func (manager *SGuestImageManager) ValidateCreateData(ctx context.Context, userC
|
||||
pendingUsage := SQuota{Image: int(imageNum)}
|
||||
keys := quotas.OwnerIdQuotaKeys(rbacutils.ScopeProject, ownerId)
|
||||
pendingUsage.SetKeys(keys)
|
||||
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
if err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
|
||||
return nil, httperrors.NewOutOfQuotaError("%s", err)
|
||||
}
|
||||
@@ -150,7 +150,7 @@ func (gi *SGuestImage) PostCreate(ctx context.Context, userCred mcclient.TokenCr
|
||||
pendingUsage := SQuota{Image: int(imageNumber)}
|
||||
keys := quotas.OwnerIdQuotaKeys(rbacutils.ScopeProject, ownerId)
|
||||
pendingUsage.SetKeys(keys)
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
|
||||
if !suc {
|
||||
gi.SetStatus(userCred, api.IMAGE_STATUS_KILLED, "create subimage failed")
|
||||
|
||||
@@ -375,7 +375,7 @@ func (manager *SImageManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
pendingUsage := SQuota{Image: 1}
|
||||
keys := quotas.OwnerIdQuotaKeys(rbacutils.ScopeProject, ownerId)
|
||||
pendingUsage.SetKeys(keys)
|
||||
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
if err := quotas.CheckSetPendingQuota(ctx, userCred, &pendingUsage); err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("%s", err)
|
||||
}
|
||||
}
|
||||
@@ -505,7 +505,7 @@ func (self *SImage) PostCreate(ctx context.Context, userCred mcclient.TokenCrede
|
||||
pendingUsage := SQuota{Image: 1}
|
||||
keys := quotas.OwnerIdQuotaKeys(rbacutils.ScopeProject, ownerId)
|
||||
pendingUsage.SetKeys(keys)
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage)
|
||||
}
|
||||
|
||||
if data.Contains("properties") {
|
||||
@@ -1277,3 +1277,26 @@ func (self *SImage) CanUpdate(data jsonutils.JSONObject) bool {
|
||||
// Only allow update description for now when Image is part of guest image
|
||||
return self.IsGuestImage.IsFalse() || (dict.Length() == 1 && dict.Contains("description"))
|
||||
}
|
||||
|
||||
func (img *SImage) GetQuotaKeys() quotas.IQuotaKeys {
|
||||
keys := SImageQuotaKeys{}
|
||||
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(rbacutils.ScopeProject, img.GetOwnerId())
|
||||
if img.GetImageType() == api.ImageTypeISO {
|
||||
keys.Type = string(api.ImageTypeISO)
|
||||
} else {
|
||||
keys.Type = string(api.ImageTypeTemplate)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func (img *SImage) GetUsages() []db.IUsage {
|
||||
if img.PendingDeleted || img.Deleted {
|
||||
return nil
|
||||
}
|
||||
usage := SQuota{Image: 1}
|
||||
keys := img.GetQuotaKeys()
|
||||
usage.SetKeys(keys)
|
||||
return []db.IUsage{
|
||||
&usage,
|
||||
}
|
||||
}
|
||||
|
||||
+46
-11
@@ -22,6 +22,7 @@ import (
|
||||
"yunion.io/x/pkg/tristate"
|
||||
|
||||
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"
|
||||
@@ -51,8 +52,6 @@ func init() {
|
||||
"quota_pending_usages",
|
||||
),
|
||||
}
|
||||
QuotaPendingUsageManager.SetVirtualObject(QuotaPendingUsageManager)
|
||||
|
||||
QuotaUsageManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaUsageManager(SQuota{},
|
||||
"quota_usage_tbl",
|
||||
@@ -60,33 +59,32 @@ func init() {
|
||||
"quota_usages",
|
||||
),
|
||||
}
|
||||
QuotaUsageManager.SetVirtualObject(QuotaUsageManager)
|
||||
|
||||
QuotaManager = &SQuotaManager{
|
||||
SQuotaBaseManager: quotas.NewQuotaBaseManager(SQuota{}, "quota_tbl", QuotaPendingUsageManager, QuotaUsageManager,
|
||||
"image_quota", "image_quotas"),
|
||||
}
|
||||
QuotaManager.SetVirtualObject(QuotaManager)
|
||||
|
||||
quotas.Register(QuotaManager)
|
||||
}
|
||||
|
||||
type SQuota struct {
|
||||
quotas.SQuotaBase
|
||||
|
||||
quotas.SBaseQuotaKeys
|
||||
SImageQuotaKeys
|
||||
|
||||
Image int
|
||||
}
|
||||
|
||||
func (self *SQuota) GetKeys() quotas.IQuotaKeys {
|
||||
return self.SBaseQuotaKeys
|
||||
return self.SImageQuotaKeys
|
||||
}
|
||||
|
||||
func (self *SQuota) SetKeys(keys quotas.IQuotaKeys) {
|
||||
self.SBaseQuotaKeys = keys.(quotas.SBaseQuotaKeys)
|
||||
self.SImageQuotaKeys = keys.(SImageQuotaKeys)
|
||||
}
|
||||
|
||||
func (self *SQuota) FetchSystemQuota() {
|
||||
keys := self.SBaseQuotaKeys
|
||||
keys := self.SImageQuotaKeys
|
||||
base := 0
|
||||
switch options.Options.DefaultQuotaValue {
|
||||
case commonOptions.DefaultQuotaUnlimit:
|
||||
@@ -115,12 +113,21 @@ func (self *SQuota) FetchSystemQuota() {
|
||||
}
|
||||
|
||||
func (self *SQuota) FetchUsage(ctx context.Context) error {
|
||||
keys := self.SBaseQuotaKeys
|
||||
keys := self.SImageQuotaKeys
|
||||
|
||||
scope := keys.Scope()
|
||||
ownerId := keys.OwnerId()
|
||||
|
||||
count := ImageManager.count(scope, ownerId, "", tristate.None, false)
|
||||
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)
|
||||
self.Image = int(count["total"].Count)
|
||||
return nil
|
||||
}
|
||||
@@ -190,3 +197,31 @@ func (manager *SQuotaManager) FetchIdNames(ctx context.Context, idMap map[string
|
||||
}
|
||||
return idMap, nil
|
||||
}
|
||||
|
||||
type SImageQuotaKeys struct {
|
||||
quotas.SBaseQuotaKeys
|
||||
|
||||
Type string `width:"16" charset:"ascii" nullable:"false" primary:"true" list:"user"`
|
||||
}
|
||||
|
||||
func (k SImageQuotaKeys) Fields() []string {
|
||||
return append(k.SBaseQuotaKeys.Fields(), "type")
|
||||
}
|
||||
|
||||
func (k SImageQuotaKeys) Values() []string {
|
||||
return append(k.SBaseQuotaKeys.Values(), k.Type)
|
||||
}
|
||||
|
||||
func (k1 SImageQuotaKeys) Compare(ik quotas.IQuotaKeys) int {
|
||||
k2 := ik.(SImageQuotaKeys)
|
||||
r := k1.SBaseQuotaKeys.Compare(k2.SBaseQuotaKeys)
|
||||
if r != 0 {
|
||||
return r
|
||||
}
|
||||
if k1.Type < k2.Type {
|
||||
return -1
|
||||
} else if k1.Type > k2.Type {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -66,6 +66,15 @@ func (this *QuotaManager) GetQuota(s *mcclient.ClientSession, params jsonutils.J
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (this *QuotaManager) DoCleanPendingUsage(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
url := this.getURL(params)
|
||||
results, err := modulebase.Delete(this.ResourceManager, s, url, nil, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (this *QuotaManager) GetQuotaList(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
var reqUrl string
|
||||
domainId := jsonutils.GetAnyString(params, []string{"domain", "project_domain", "domain_id", "project_domain_id"})
|
||||
|
||||
Reference in New Issue
Block a user