diff --git a/internal/controller/dispatcher.go b/internal/controller/dispatcher.go index 7c0ba9a..4b1c307 100644 --- a/internal/controller/dispatcher.go +++ b/internal/controller/dispatcher.go @@ -394,7 +394,7 @@ func (r *Dispatcher) getUnadmittedPodsWeights(ctx context.Context) (map[string]* for _, pod := range pods.Items { createdPodsWeightsPair.Add(NewWeightsPairForPod(&pod)) } - weightsPair.Sub(createdPodsWeightsPair) + weightsPair.QuotaSub(createdPodsWeightsPair) } nonNegativeWeightsPair := NewWeightsPair(Weights{}, Weights{}) nonNegativeWeightsPair.Max(weightsPair) diff --git a/internal/controller/quota_tracker.go b/internal/controller/quota_tracker.go index 14d418d..9807e21 100644 --- a/internal/controller/quota_tracker.go +++ b/internal/controller/quota_tracker.go @@ -17,6 +17,7 @@ limitations under the License. package controller import ( + "fmt" "strings" mcadv1beta1 "github.com/project-codeflare/mcad/api/v1beta1" @@ -82,12 +83,13 @@ func (tracker *QuotaTracker) Satisfies(appWrapperAskWeights *WeightsPair, resour } // check if both appwrapper requests and limits fit available resource quota quotaWeights := quotaState.quota.Clone() - quotaWeights.Sub(quotaState.used) - quotaWeights.Sub(quotaState.allocated) + quotaWeights.QuotaSub(quotaState.used) + quotaWeights.QuotaSub(quotaState.allocated) var unAdmittedWeights *WeightsPair if unAdmittedWeights, exists = tracker.unAdmittedWeightsMap[namespace]; exists { - quotaWeights.Sub(unAdmittedWeights) + quotaWeights.QuotaSub(unAdmittedWeights) } + fmt.Println(quotaWeights) quotaFits, insufficientResources := appWrapperAskWeights.Fits(quotaWeights) // mcadLog.Info("QuotaTracker.Satisfies():", "namespace", namespace, diff --git a/internal/controller/weights.go b/internal/controller/weights.go index e5f2cb2..b137614 100644 --- a/internal/controller/weights.go +++ b/internal/controller/weights.go @@ -77,6 +77,16 @@ func (w Weights) Sub(r Weights) { } } +// Subtract use from quota +func (w Weights) QuotaSub(r Weights) { + for k, v := range r { + if w[k] == nil { + continue // ignore undefined quota + } + w[k].Sub(w[k], v) + } +} + // Add coefficient * weights to receiver func (w Weights) AddProd(coefficient int32, r Weights) { for k, v := range r { @@ -123,6 +133,28 @@ func (w Weights) Fits(r Weights) (bool, []v1.ResourceName) { } } +// Compare receiver to argument +// True if receiver is less than or equal to argument in every dimension where argument is defined +func (w Weights) QuotaFits(r Weights) (bool, []v1.ResourceName) { + insufficient := []v1.ResourceName{} + zero := &inf.Dec{} // shared zero, never mutated + for k, v := range w { // range over receiver not argument + // ignore 0 requests or no quota + if v.Cmp(zero) <= 0 || r[k] == nil { + continue + } + // v > 0 so r[k] must be no less than v + if v.Cmp(r[k]) == 1 { + insufficient = append(insufficient, k) + } + } + if len(insufficient) == 0 { + return true, nil + } else { + return false, insufficient + } +} + // Converts Weights to a ResourceList func (w Weights) AsResources() v1.ResourceList { resources := v1.ResourceList{} @@ -161,9 +193,9 @@ func (w *WeightsPair) Add(r *WeightsPair) { } // Subtract pair of weights from receiver -func (w *WeightsPair) Sub(r *WeightsPair) { - w.requests.Sub(r.requests) - w.limits.Sub(r.limits) +func (w *WeightsPair) QuotaSub(r *WeightsPair) { + w.requests.QuotaSub(r.requests) + w.limits.QuotaSub(r.limits) } // Max of two pairs of weights @@ -184,8 +216,8 @@ func (w *WeightsPair) Clone() *WeightsPair { // If False, return list of insufficient resource names func (w *WeightsPair) Fits(r *WeightsPair) (bool, []v1.ResourceName) { insufficient := []v1.ResourceName{} - requestsFits, requestsInsufficient := w.requests.Fits(r.requests) - limitsFits, limitsInsufficient := w.limits.Fits(r.limits) + requestsFits, requestsInsufficient := w.requests.QuotaFits(r.requests) + limitsFits, limitsInsufficient := w.limits.QuotaFits(r.limits) if requestsFits && limitsFits { return true, insufficient }