This is an automated email from the ASF dual-hosted git repository.

mani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/yunikorn-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 98ab7f80 [YUNIKORN-3142] Calculate Preemptable Resource for leaf Queue 
with same resource types (#1039)
98ab7f80 is described below

commit 98ab7f80d5db4c8f6c4ef29db14853e4f8283da5
Author: mani <[email protected]>
AuthorDate: Mon Nov 10 11:16:01 2025 +0530

    [YUNIKORN-3142] Calculate Preemptable Resource for leaf Queue with same 
resource types (#1039)
    
    Closes: #1039
    
    Signed-off-by: mani <[email protected]>
---
 pkg/scheduler/objects/queue.go                     |  6 ++++
 pkg/scheduler/objects/quota_change_preemptor.go    | 29 ++++++++++++++++++++
 .../objects/quota_change_preemptor_test.go         | 32 ++++++++++++++++++++++
 3 files changed, 67 insertions(+)

diff --git a/pkg/scheduler/objects/queue.go b/pkg/scheduler/objects/queue.go
index 71f30d6d..f21ef498 100644
--- a/pkg/scheduler/objects/queue.go
+++ b/pkg/scheduler/objects/queue.go
@@ -1338,6 +1338,12 @@ func (sq *Queue) GetMaxResource() *resources.Resource {
        return sq.internalGetMax(limit)
 }
 
+func (sq *Queue) CloneMaxResource() *resources.Resource {
+       sq.RLock()
+       defer sq.RUnlock()
+       return sq.maxResource.Clone()
+}
+
 // GetFairMaxResource computes the fair max resources for a given queue.
 // Starting with the root, descend down to the target queue allowing children 
to override Resource values .
 // If the root includes an explicit 0 value for a Resource, do not include it 
in the accumulator and treat it as missing.
diff --git a/pkg/scheduler/objects/quota_change_preemptor.go 
b/pkg/scheduler/objects/quota_change_preemptor.go
index 8634ba2b..f277a3da 100644
--- a/pkg/scheduler/objects/quota_change_preemptor.go
+++ b/pkg/scheduler/objects/quota_change_preemptor.go
@@ -18,6 +18,12 @@
 
 package objects
 
+import (
+       "math"
+
+       "github.com/apache/yunikorn-core/pkg/common/resources"
+)
+
 type QuotaChangePreemptionContext struct {
        queue *Queue
 }
@@ -48,3 +54,26 @@ func (qcp *QuotaChangePreemptionContext) tryPreemption() {
        // quota change preemption has really evicted victims, so mark the flag
        qcp.queue.MarkTriggerredQuotaChangePreemption()
 }
+
+// GetPreemptableResources Get the preemptable resources for the queue
+// Subtracting the usage from the max resource gives the preemptable resources.
+// It could contain both positive and negative values. Only negative values 
are preemptable.
+func (qcp *QuotaChangePreemptionContext) GetPreemptableResources() 
*resources.Resource {
+       maxRes := qcp.queue.CloneMaxResource()
+       used := resources.SubOnlyExisting(qcp.queue.GetAllocatedResource(), 
qcp.queue.GetPreemptingResource())
+       if maxRes.IsEmpty() || used.IsEmpty() {
+               return nil
+       }
+       actual := resources.SubOnlyExisting(maxRes, used)
+       preemptableResource := resources.NewResource()
+       // Keep only the resource type which needs to be preempted
+       for k, v := range actual.Resources {
+               if v < 0 {
+                       preemptableResource.Resources[k] = 
resources.Quantity(math.Abs(float64(v)))
+               }
+       }
+       if preemptableResource.IsEmpty() {
+               return nil
+       }
+       return preemptableResource
+}
diff --git a/pkg/scheduler/objects/quota_change_preemptor_test.go 
b/pkg/scheduler/objects/quota_change_preemptor_test.go
index f7cd673d..7052c841 100644
--- a/pkg/scheduler/objects/quota_change_preemptor_test.go
+++ b/pkg/scheduler/objects/quota_change_preemptor_test.go
@@ -99,3 +99,35 @@ func TestQuotaChangeCheckPreconditions(t *testing.T) {
                })
        }
 }
+
+func TestQuotaChangeGetPreemptableResource(t *testing.T) {
+       leaf, err := NewConfiguredQueue(configs.QueueConfig{
+               Name: "leaf",
+       }, nil, false, nil)
+       assert.NilError(t, err)
+
+       testCases := []struct {
+               name         string
+               queue        *Queue
+               maxResource  *resources.Resource
+               usedResource *resources.Resource
+               preemptable  *resources.Resource
+       }{
+               {"nil max and nil used", leaf, nil, nil, nil},
+               {"nil max", leaf, nil, 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1000}), 
nil},
+               {"nil used", leaf, 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1000}), 
nil, nil},
+               {"used below max", leaf, 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1000}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 500}), 
nil},
+               {"used above max", leaf, 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1000}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1500}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 500})},
+               {"used above max in specific res type", leaf, 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1000, 
"cpu": 10}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1500}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 500})},
+               {"used above max and below max in specific res type", leaf, 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1000, 
"cpu": 10}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1500, 
"cpu": 10}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 500})},
+               {"used res type but max undefined", leaf, 
resources.NewResourceFromMap(map[string]resources.Quantity{"memory": 1000}), 
resources.NewResourceFromMap(map[string]resources.Quantity{"cpu": 150}), nil},
+       }
+       for _, tc := range testCases {
+               t.Run(tc.name, func(t *testing.T) {
+                       tc.queue.maxResource = tc.maxResource
+                       tc.queue.allocatedResource = tc.usedResource
+                       preemptor := NewQuotaChangePreemptor(tc.queue)
+                       assert.Equal(t, 
resources.Equals(preemptor.GetPreemptableResources(), tc.preemptable), true)
+               })
+       }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to