fix: server change config failed due to quota recode

This commit is contained in:
Qiu Jian
2019-12-16 20:44:18 +08:00
parent db2b599dcd
commit bdfa99b0b6
6 changed files with 75 additions and 46 deletions

View File

@@ -153,7 +153,14 @@ func (manager *SQuotaBaseManager) getQuotasInternal(ctx context.Context, keys IQ
}
func (manager *SQuotaBaseManager) setQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, quota IQuota) error {
return manager.TableSpec().InsertOrUpdate(quota)
err := manager.TableSpec().InsertOrUpdate(quota)
if err != nil {
return errors.Wrap(err, "InsertOrUpdate")
}
if manager.nonNegative {
quota.ResetNegative()
}
return nil
}
func (manager *SQuotaBaseManager) addQuotaInternal(ctx context.Context, userCred mcclient.TokenCredential, diff IQuota) error {

View File

@@ -69,7 +69,7 @@ func (manager *SQuotaBaseManager) cancelPendingUsage(ctx context.Context, userCr
func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userCred mcclient.TokenCredential, localUsage IQuota, cancelUsage IQuota) error {
originKeys := localUsage.GetKeys()
currentKeys := cancelUsage.GetKeys()
// currentKeys := cancelUsage.GetKeys()
pendingUsage := manager.newQuota()
pendingUsage.SetKeys(originKeys)
@@ -79,9 +79,6 @@ func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userC
if err != nil {
return errors.Wrap(err, "manager.pendingStore.SubQuota")
}
// save cancelUsage values
subUsage := manager.newQuota()
subUsage.Update(cancelUsage)
//
if localUsage != nil {
localUsage.Sub(cancelUsage)
@@ -89,18 +86,11 @@ func (manager *SQuotaBaseManager) _cancelPendingUsage(ctx context.Context, userC
log.Debugf("cancelUsage: %s localUsage: %s", jsonutils.Marshal(cancelUsage), jsonutils.Marshal(localUsage))
// update usages
quotas, err := manager.usageStore.GetParentQuotas(ctx, currentKeys)
err = manager.changeUsage(ctx, userCred, cancelUsage, true)
if err != nil {
return errors.Wrap(err, "manager.usageStore.GetParentQuotas")
}
for i := range quotas {
subUsage.SetKeys(quotas[i].GetKeys())
err := manager.usageStore.AddQuota(ctx, userCred, subUsage)
if err != nil {
return errors.Wrap(err, "manager.usageStore.AddQuota")
}
return errors.Wrap(err, "manager.changelUsage")
}
return nil
}
@@ -112,6 +102,10 @@ func (manager *SQuotaBaseManager) cancelUsage(ctx context.Context, userCred mccl
}
func (manager *SQuotaBaseManager) _cancelUsage(ctx context.Context, userCred mcclient.TokenCredential, usage IQuota) error {
return manager.changeUsage(ctx, userCred, usage, false)
}
func (manager *SQuotaBaseManager) changeUsage(ctx context.Context, userCred mcclient.TokenCredential, usage IQuota, isAdd bool) error {
usages, err := manager.usageStore.GetParentQuotas(ctx, usage.GetKeys())
if err != nil {
return errors.Wrap(err, "manager.usageStore.GetParentQuotas")
@@ -120,9 +114,16 @@ func (manager *SQuotaBaseManager) _cancelUsage(ctx context.Context, userCred mcc
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")
if isAdd {
err := manager.usageStore.AddQuota(ctx, userCred, subUsage)
if err != nil {
return errors.Wrap(err, "manager.usageStore.AddQuota")
}
} else {
err := manager.usageStore.SubQuota(ctx, userCred, subUsage)
if err != nil {
return errors.Wrap(err, "manager.usageStore.SubQuota")
}
}
}
return nil
@@ -203,16 +204,23 @@ func (manager *SQuotaBaseManager) checkQuota(ctx context.Context, request IQuota
}
func (manager *SQuotaBaseManager) __checkQuota(ctx context.Context, quota IQuota, request IQuota) error {
keys := quota.GetKeys()
log.Debugf("__checkQuota for keys: %s", QuotaKeyString(keys))
used := manager.newQuota()
err := manager.usageStore.GetQuota(ctx, quota.GetKeys(), used)
err := manager.usageStore.GetQuota(ctx, keys, used)
if err != nil {
return errors.Wrap(err, "manager.usageStore.GetQuotaByKeys")
}
pendings, err := manager.pendingStore.GetChildrenQuotas(ctx, quota.GetKeys())
log.Debugf("__checkQuota usage: %s", jsonutils.Marshal(used))
pendings, err := manager.pendingStore.GetChildrenQuotas(ctx, keys)
if err != nil {
return errors.Wrap(err, "manager.pendingStore.GetChildrenQuotas")
}
for i := range pendings {
if pendings[i].IsEmpty() {
continue
}
log.Debugf("__checkQuota pending %d: %s", i, jsonutils.Marshal(pendings[i]))
used.Add(pendings[i])
}
return used.Exceed(request, quota)

View File

@@ -27,6 +27,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/pkg/util/stringutils"
@@ -226,7 +227,7 @@ func fetchTaskParams(
if len(pendingUsages) > 0 {
for i := range pendingUsages {
pendingUsage := pendingUsages[i]
if gotypes.IsNil(pendingUsage) || pendingUsage.IsEmpty() {
if gotypes.IsNil(pendingUsage) {
continue
}
key := pendingUsageKey(i)
@@ -709,11 +710,17 @@ func (self *STask) IsCurrentStageComplete() bool {
func (self *STask) GetPendingUsage(quota quotas.IQuota, index int) error {
key := pendingUsageKey(index)
quotaJson, err := self.Params.Get(key)
if err != nil {
return err
if self.Params.Contains(key) {
quotaJson, err := self.Params.Get(key)
if err != nil {
return errors.Wrapf(err, "task.Params.Get %s", key)
}
err = quotaJson.Unmarshal(quota)
if err != nil {
return errors.Wrap(err, "quotaJson.Unmarshal")
}
}
return quotaJson.Unmarshal(quota)
return nil
}
func pendingUsageKey(index int) string {

View File

@@ -2395,11 +2395,10 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
return nil, err
}
pendingUsage.SetKeys(keys)
if !pendingUsage.IsEmpty() {
err := quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
if err != nil {
return nil, err
}
log.Debugf("ChangeConfig pendingUsage %s", jsonutils.Marshal(pendingUsage))
err = quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage)
if err != nil {
return nil, err
}
if len(newDisks) > 0 {

View File

@@ -199,10 +199,10 @@ func (self *GuestChangeConfigTask) OnGuestChangeCpuMemSpecComplete(ctx context.C
return
}
changeConfigSpec := jsonutils.NewDict()
if addCpu > 0 {
if addCpu != 0 {
changeConfigSpec.Set("add_cpu", jsonutils.NewInt(int64(addCpu)))
}
if addMem > 0 {
if addMem != 0 {
changeConfigSpec.Set("add_mem", jsonutils.NewInt(int64(addMem)))
}
if len(instanceType) > 0 {
@@ -218,11 +218,16 @@ func (self *GuestChangeConfigTask) OnGuestChangeCpuMemSpecComplete(ctx context.C
return
}
var cancelUsage models.SQuota
var reduceUsage models.SQuota
if addCpu > 0 {
cancelUsage.Cpu = addCpu
} else if addCpu < 0 {
reduceUsage.Cpu = -addCpu
}
if addMem > 0 {
cancelUsage.Memory = addMem
} else if addMem < 0 {
reduceUsage.Memory = -addMem
}
keys, err := guest.GetQuotaKeys()
@@ -231,19 +236,26 @@ func (self *GuestChangeConfigTask) OnGuestChangeCpuMemSpecComplete(ctx context.C
return
}
cancelUsage.SetKeys(keys)
reduceUsage.SetKeys(keys)
lockman.LockClass(ctx, guest.GetModelManager(), guest.ProjectId)
defer lockman.ReleaseClass(ctx, guest.GetModelManager(), guest.ProjectId)
err = quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &cancelUsage)
if err != nil {
self.markStageFailed(ctx, guest, fmt.Sprintf("CancelPendingUsage fail %s", err))
return
if !cancelUsage.IsEmpty() {
err = quotas.CancelPendingUsage(ctx, self.UserCred, &pendingUsage, &cancelUsage)
if err != nil {
self.markStageFailed(ctx, guest, fmt.Sprintf("CancelPendingUsage fail %s", err))
return
}
err = self.SetPendingUsage(&pendingUsage, 0)
if err != nil {
self.markStageFailed(ctx, guest, fmt.Sprintf("SetPendingUsage fail %s", err))
return
}
}
err = self.SetPendingUsage(&pendingUsage, 0)
if err != nil {
self.markStageFailed(ctx, guest, fmt.Sprintf("SetPendingUsage fail %s", err))
return
if !reduceUsage.IsEmpty() {
quotas.CancelUsages(ctx, self.UserCred, []db.IUsage{&reduceUsage})
}
self.OnGuestChangeCpuMemSpecFinish(ctx, guest)

View File

@@ -61,12 +61,8 @@ func JsonClientError(w http.ResponseWriter, e *httputils.JSONClientError) {
}
func GeneralServerError(w http.ResponseWriter, e error) {
je, ok := e.(*httputils.JSONClientError)
if ok {
JsonClientError(w, je)
} else {
InternalServerError(w, "%s", e)
}
je := NewGeneralError(e)
JsonClientError(w, je)
}
func BadRequestError(w http.ResponseWriter, msg string, params ...interface{}) {