You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@yunikorn.apache.org by cc...@apache.org on 2024/06/25 21:03:12 UTC
(yunikorn-core) branch master updated: [YUNIKORN-2700] Use AllocationResult instead of Allocation in scheduler routines (#902)
This is an automated email from the ASF dual-hosted git repository.
ccondit 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 87b1d7cf [YUNIKORN-2700] Use AllocationResult instead of Allocation in scheduler routines (#902)
87b1d7cf is described below
commit 87b1d7cf4d083fca75ea389ca025327b18bffd9a
Author: Craig Condit <cc...@apache.org>
AuthorDate: Tue Jun 25 16:02:58 2024 -0500
[YUNIKORN-2700] Use AllocationResult instead of Allocation in scheduler routines (#902)
Closes: #902
---
pkg/scheduler/context.go | 18 +-
pkg/scheduler/objects/allocation.go | 92 ++--
pkg/scheduler/objects/allocation_test.go | 82 +++-
pkg/scheduler/objects/application.go | 135 +++---
pkg/scheduler/objects/application_test.go | 92 ++--
pkg/scheduler/objects/preemption.go | 4 +-
pkg/scheduler/objects/preemption_test.go | 104 +++--
pkg/scheduler/objects/queue.go | 51 ++-
pkg/scheduler/partition.go | 72 +--
pkg/scheduler/partition_test.go | 711 +++++++++++++++---------------
10 files changed, 708 insertions(+), 653 deletions(-)
diff --git a/pkg/scheduler/context.go b/pkg/scheduler/context.go
index 9fe37996..39715b44 100644
--- a/pkg/scheduler/context.go
+++ b/pkg/scheduler/context.go
@@ -130,22 +130,22 @@ func (cc *ClusterContext) schedule() bool {
}
// try reservations first
schedulingStart := time.Now()
- alloc := psc.tryReservedAllocate()
- if alloc == nil {
+ result := psc.tryReservedAllocate()
+ if result == nil {
// placeholder replacement second
- alloc = psc.tryPlaceholderAllocate()
+ result = psc.tryPlaceholderAllocate()
// nothing reserved that can be allocated try normal allocate
- if alloc == nil {
- alloc = psc.tryAllocate()
+ if result == nil {
+ result = psc.tryAllocate()
}
}
- if alloc != nil {
+ if result != nil {
metrics.GetSchedulerMetrics().ObserveSchedulingLatency(schedulingStart)
- if alloc.GetResultType() == objects.Replaced {
+ if result.ResultType == objects.Replaced {
// communicate the removal to the RM
- cc.notifyRMAllocationReleased(psc.RmID, psc.Name, []*objects.Allocation{alloc.GetRelease()}, si.TerminationType_PLACEHOLDER_REPLACED, "replacing allocationKey: "+alloc.GetAllocationKey())
+ cc.notifyRMAllocationReleased(psc.RmID, psc.Name, []*objects.Allocation{result.Allocation.GetRelease()}, si.TerminationType_PLACEHOLDER_REPLACED, "replacing allocationKey: "+result.Ask.GetAllocationKey())
} else {
- cc.notifyRMNewAllocation(psc.RmID, alloc)
+ cc.notifyRMNewAllocation(psc.RmID, result.Allocation)
}
activity = true
}
diff --git a/pkg/scheduler/objects/allocation.go b/pkg/scheduler/objects/allocation.go
index f6a3c27a..ddbfe6bf 100644
--- a/pkg/scheduler/objects/allocation.go
+++ b/pkg/scheduler/objects/allocation.go
@@ -43,8 +43,27 @@ const (
Replaced
)
-func (ar AllocationResultType) String() string {
- return [...]string{"None", "Allocated", "AllocatedReserved", "Reserved", "Unreserved", "Replaced"}[ar]
+func (art AllocationResultType) String() string {
+ return [...]string{"None", "Allocated", "AllocatedReserved", "Reserved", "Unreserved", "Replaced"}[art]
+}
+
+type AllocationResult struct {
+ ResultType AllocationResultType
+ NodeID string
+ ReservedNodeID string
+ Ask *AllocationAsk
+ Allocation *Allocation
+}
+
+func (ar *AllocationResult) String() string {
+ if ar == nil {
+ return "nil allocation result"
+ }
+ allocationKey := ""
+ if ar.Ask != nil {
+ allocationKey = ar.Ask.GetAllocationKey()
+ }
+ return fmt.Sprintf("resultType=%s, nodeID=%s, reservedNodeID=%s, allocationKey=%s", ar.ResultType.String(), ar.NodeID, ar.ReservedNodeID, allocationKey)
}
type Allocation struct {
@@ -65,8 +84,6 @@ type Allocation struct {
bindTime time.Time // the time this allocation was bound to a node
placeholderCreateTime time.Time
released bool
- reservedNodeID string
- resultType AllocationResultType
release *Allocation
preempted bool
instType string
@@ -87,22 +104,37 @@ func NewAllocation(nodeID string, ask *AllocationAsk) *Allocation {
allocatedResource: ask.GetAllocatedResource().Clone(),
taskGroupName: ask.GetTaskGroup(),
placeholder: ask.IsPlaceholder(),
- resultType: Allocated,
}
}
-func newReservedAllocation(nodeID string, ask *AllocationAsk) *Allocation {
- alloc := NewAllocation(nodeID, ask)
- alloc.SetBindTime(time.Time{})
- alloc.SetResultType(Reserved)
- return alloc
+// newAllocatedAllocationResult creates a new allocation result for a new allocation.
+func newAllocatedAllocationResult(nodeID string, ask *AllocationAsk, alloc *Allocation) *AllocationResult {
+ return newAllocationResultInternal(Allocated, nodeID, ask, alloc)
+}
+
+// newReservedAllocationResult creates a new allocation result for reserving a node.
+func newReservedAllocationResult(nodeID string, ask *AllocationAsk) *AllocationResult {
+ return newAllocationResultInternal(Reserved, nodeID, ask, nil)
}
-func newUnreservedAllocation(nodeID string, ask *AllocationAsk) *Allocation {
- alloc := NewAllocation(nodeID, ask)
- alloc.SetBindTime(time.Time{})
- alloc.SetResultType(Unreserved)
- return alloc
+// newUnreservedAllocationResult creates a new allocation result for unreserving a node.
+func newUnreservedAllocationResult(nodeID string, ask *AllocationAsk) *AllocationResult {
+ return newAllocationResultInternal(Unreserved, nodeID, ask, nil)
+}
+
+// newReplacedAllocationResult create a new allocation result for replaced allocations.
+func newReplacedAllocationResult(nodeID string, ask *AllocationAsk, alloc *Allocation) *AllocationResult {
+ return newAllocationResultInternal(Replaced, nodeID, ask, alloc)
+}
+
+// newAllocationResultInternal creates a new allocation result. It should not be called directly.
+func newAllocationResultInternal(resultType AllocationResultType, nodeID string, ask *AllocationAsk, alloc *Allocation) *AllocationResult {
+ return &AllocationResult{
+ ResultType: resultType,
+ NodeID: nodeID,
+ Ask: ask,
+ Allocation: alloc,
+ }
}
// Create a new Allocation from a node recovered allocation.
@@ -179,7 +211,7 @@ func (a *Allocation) String() string {
}
a.RLock()
defer a.RUnlock()
- return fmt.Sprintf("applicationID=%s, allocationKey=%s, Node=%s, resultType=%s", a.applicationID, a.allocationKey, a.nodeID, a.resultType.String())
+ return fmt.Sprintf("applicationID=%s, allocationKey=%s, Node=%s", a.applicationID, a.allocationKey, a.nodeID)
}
// GetAsk returns the ask associated with this allocation
@@ -277,20 +309,6 @@ func (a *Allocation) GetPriority() int32 {
return a.priority
}
-// GetReservedNodeID gets the node this allocation is reserved for
-func (a *Allocation) GetReservedNodeID() string {
- a.RLock()
- defer a.RUnlock()
- return a.reservedNodeID
-}
-
-// SetReservedNodeID sets the node this allocation is reserved for
-func (a *Allocation) SetReservedNodeID(reservedNodeID string) {
- a.Lock()
- defer a.Unlock()
- a.reservedNodeID = reservedNodeID
-}
-
// IsReleased returns the release status of the allocation
func (a *Allocation) IsReleased() bool {
a.RLock()
@@ -310,20 +328,6 @@ func (a *Allocation) GetTagsClone() map[string]string {
return CloneAllocationTags(a.tags)
}
-// GetResultType gets the result type of this allocation
-func (a *Allocation) GetResultType() AllocationResultType {
- a.RLock()
- defer a.RUnlock()
- return a.resultType
-}
-
-// SetResultType sets the result type of this allocation
-func (a *Allocation) SetResultType(resultType AllocationResultType) {
- a.Lock()
- defer a.Unlock()
- a.resultType = resultType
-}
-
// GetRelease returns the associated release for this allocation
func (a *Allocation) GetRelease() *Allocation {
a.RLock()
diff --git a/pkg/scheduler/objects/allocation_test.go b/pkg/scheduler/objects/allocation_test.go
index b7b26bb0..77f3c2c5 100644
--- a/pkg/scheduler/objects/allocation_test.go
+++ b/pkg/scheduler/objects/allocation_test.go
@@ -54,7 +54,6 @@ func TestNewAlloc(t *testing.T) {
t.Fatal("NewAllocation create failed while it should not")
}
assert.Equal(t, alloc.GetAllocationKey(), "ask-1")
- assert.Equal(t, alloc.GetResultType(), Allocated, "New alloc should default to result type Allocated")
assert.Assert(t, resources.Equals(alloc.GetAllocatedResource(), res), "Allocated resource not set correctly")
assert.Assert(t, !alloc.IsPlaceholder(), "ask should not have been a placeholder")
assert.Equal(t, time.Now().Round(time.Second), alloc.GetCreateTime().Round(time.Second))
@@ -62,7 +61,7 @@ func TestNewAlloc(t *testing.T) {
alloc.SetInstanceType(instType1)
assert.Equal(t, alloc.GetInstanceType(), instType1, "Instance type not set as expected")
allocStr := alloc.String()
- expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1, resultType=Allocated"
+ expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1"
assert.Equal(t, allocStr, expected, "Strings should have been equal")
assert.Assert(t, !alloc.IsPlaceholderUsed(), fmt.Sprintf("Alloc should not be placeholder replacement by default: got %t, expected %t", alloc.IsPlaceholderUsed(), false))
// check that createTime is properly copied from the ask
@@ -74,34 +73,77 @@ func TestNewAlloc(t *testing.T) {
assert.Equal(t, alloc.GetCreateTime(), ask.GetCreateTime(), "createTime was not copied from the ask")
}
-func TestNewReservedAlloc(t *testing.T) {
+func TestNewAllocatedAllocationResult(t *testing.T) {
res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
assert.NilError(t, err, "Resource creation failed")
ask := newAllocationAsk("ask-1", "app-1", res)
- alloc := newReservedAllocation("node-1", ask)
- if alloc == nil {
- t.Fatal("NewReservedAllocation create failed while it should not")
+ alloc := NewAllocation("node-1", ask)
+ result := newAllocatedAllocationResult("node-1", ask, alloc)
+ if result == nil {
+ t.Fatal("NewAllocatedAllocationResult create failed while it should not")
}
- assert.Equal(t, alloc.GetResultType(), Reserved, "NewReservedAlloc should have Reserved result type")
- assert.Assert(t, resources.Equals(alloc.GetAllocatedResource(), res), "Allocated resource not set correctly")
- allocStr := alloc.String()
- expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1, resultType=Reserved"
- assert.Equal(t, allocStr, expected, "Strings should have been equal")
+ assert.Equal(t, result.ResultType, Allocated, "NewAllocatedAllocationResult should have Allocated result type")
+ assert.Equal(t, ask, result.Ask, "wrong ask")
+ assert.Equal(t, alloc, result.Allocation, "wrong allocation")
+ assert.Equal(t, result.NodeID, "node-1", "wrong node id")
}
-func TestNewUnreservedAlloc(t *testing.T) {
+func TestNewReservedAllocationResult(t *testing.T) {
res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
assert.NilError(t, err, "Resource creation failed")
ask := newAllocationAsk("ask-1", "app-1", res)
- alloc := newUnreservedAllocation("node-1", ask)
- if alloc == nil {
- t.Fatal("NewReservedAllocation create failed while it should not")
+ result := newReservedAllocationResult("node-1", ask)
+ if result == nil {
+ t.Fatal("NewReservedAllocationResult create failed while it should not")
}
- assert.Equal(t, alloc.GetResultType(), Unreserved, "NewReservedAlloc should have Reserved result type")
- assert.Assert(t, resources.Equals(alloc.GetAllocatedResource(), res), "Allocated resource not set correctly")
- allocStr := alloc.String()
- expected := "applicationID=app-1, allocationKey=ask-1, Node=node-1, resultType=Unreserved"
- assert.Equal(t, allocStr, expected, "Strings should have been equal")
+ assert.Equal(t, result.ResultType, Reserved, "NewReservedAllocationResult should have Reserved result type")
+ assert.Equal(t, ask, result.Ask, "wrong ask")
+ assert.Equal(t, result.NodeID, "node-1", "wrong node id")
+}
+
+func TestNewUnreservedAllocationResult(t *testing.T) {
+ res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
+ assert.NilError(t, err, "Resource creation failed")
+ ask := newAllocationAsk("ask-1", "app-1", res)
+ result := newUnreservedAllocationResult("node-1", ask)
+ if result == nil {
+ t.Fatal("NewReservedAllocationResult create failed while it should not")
+ }
+ assert.Equal(t, result.ResultType, Unreserved, "NewReservedAllocationResult should have Reserved result type")
+ assert.Equal(t, ask, result.Ask, "wrong ask")
+ assert.Equal(t, result.NodeID, "node-1", "wrong node id")
+}
+
+func TestNewReplacedAllocationResult(t *testing.T) {
+ res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
+ assert.NilError(t, err, "Resource creation failed")
+ ask := newAllocationAsk("ask-1", "app-1", res)
+ alloc := NewAllocation("node-1", ask)
+ result := newReplacedAllocationResult("node-1", ask, alloc)
+ if result == nil {
+ t.Fatal("NewReplacedllocationResult create failed while it should not")
+ }
+ assert.Equal(t, result.ResultType, Replaced, "NewReplacedAllocationResult should have Allocated result type")
+ assert.Equal(t, ask, result.Ask, "wrong ask")
+ assert.Equal(t, alloc, result.Allocation, "wrong allocation")
+ assert.Equal(t, result.NodeID, "node-1", "wrong node id")
+}
+
+func TestAllocationResultString(t *testing.T) {
+ res, err := resources.NewResourceFromConf(map[string]string{"first": "1"})
+ assert.NilError(t, err, "Resource creation failed")
+ ask := newAllocationAsk("ask-1", "app-1", res)
+ result := &AllocationResult{
+ ResultType: Allocated,
+ NodeID: "node-1",
+ ReservedNodeID: "node-2",
+ Ask: ask,
+ }
+ assert.Equal(t, result.String(), "resultType=Allocated, nodeID=node-1, reservedNodeID=node-2, allocationKey=ask-1", "wrong content")
+
+ // validate nil ask
+ result.Ask = nil
+ assert.Equal(t, result.String(), "resultType=Allocated, nodeID=node-1, reservedNodeID=node-2, allocationKey=", "wrong content")
}
func TestSIFromNilAlloc(t *testing.T) {
diff --git a/pkg/scheduler/objects/application.go b/pkg/scheduler/objects/application.go
index 797c5d5a..e3325f57 100644
--- a/pkg/scheduler/objects/application.go
+++ b/pkg/scheduler/objects/application.go
@@ -946,7 +946,7 @@ func (sa *Application) canReplace(request *AllocationAsk) bool {
}
// tryAllocate will perform a regular allocation of a pending request, includes placeholders.
-func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption bool, preemptionDelay time.Duration, preemptAttemptsRemaining *int, nodeIterator func() NodeIterator, fullNodeIterator func() NodeIterator, getNodeFn func(string) *Node) *Allocation {
+func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption bool, preemptionDelay time.Duration, preemptAttemptsRemaining *int, nodeIterator func() NodeIterator, fullNodeIterator func() NodeIterator, getNodeFn func(string) *Node) *AllocationResult {
sa.Lock()
defer sa.Unlock()
if sa.sortedRequests == nil {
@@ -981,9 +981,9 @@ func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption
*preemptAttemptsRemaining--
fullIterator := fullNodeIterator()
if fullIterator != nil {
- if alloc, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, false); ok {
+ if result, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, false); ok {
// preemption occurred, and possibly reservation
- return alloc
+ return result
}
}
}
@@ -1013,31 +1013,31 @@ func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption
return nil
}
}
- alloc := sa.tryNode(node, request)
- if alloc != nil {
+ result := sa.tryNode(node, request)
+ if result != nil {
// check if the node was reserved and we allocated after a release
if _, ok := sa.reservations[reservationKey(node, nil, request)]; ok {
log.Log(log.SchedApplication).Debug("allocation on required node after release",
zap.String("appID", sa.ApplicationID),
zap.String("nodeID", requiredNode),
zap.String("allocationKey", request.GetAllocationKey()))
- alloc.SetResultType(AllocatedReserved)
- return alloc
+ result.ResultType = AllocatedReserved
+ return result
}
log.Log(log.SchedApplication).Debug("allocation on required node is completed",
zap.String("nodeID", node.NodeID),
zap.String("allocationKey", request.GetAllocationKey()),
- zap.Stringer("resultType", alloc.GetResultType()))
- return alloc
+ zap.Stringer("resultType", result.ResultType))
+ return result
}
- return newReservedAllocation(node.NodeID, request)
+ return newReservedAllocationResult(node.NodeID, request)
}
iterator := nodeIterator()
if iterator != nil {
- if alloc := sa.tryNodes(request, iterator); alloc != nil {
+ if result := sa.tryNodes(request, iterator); result != nil {
// have a candidate return it
- return alloc
+ return result
}
// no nodes qualify, attempt preemption
@@ -1045,9 +1045,9 @@ func (sa *Application) tryAllocate(headRoom *resources.Resource, allowPreemption
*preemptAttemptsRemaining--
fullIterator := fullNodeIterator()
if fullIterator != nil {
- if alloc, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, true); ok {
+ if result, ok := sa.tryPreemption(headRoom, preemptionDelay, request, fullIterator, true); ok {
// preemption occurred, and possibly reservation
- return alloc
+ return result
}
}
}
@@ -1106,7 +1106,7 @@ func (sa *Application) cancelReservations(reservations []*reservation) bool {
// tryPlaceholderAllocate tries to replace a placeholder that is allocated with a real allocation
//
//nolint:funlen
-func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator, getNodeFn func(string) *Node) *Allocation {
+func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator, getNodeFn func(string) *Node) *AllocationResult {
sa.Lock()
defer sa.Unlock()
// nothing to do if we have no placeholders allocated
@@ -1164,7 +1164,8 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
alloc.SetRelease(ph)
// placeholder point to the real one in the releases list
ph.SetRelease(alloc)
- alloc.SetResultType(Replaced)
+
+ result := newReplacedAllocationResult(node.NodeID, request, alloc)
// mark placeholder as released
ph.SetReleased(true)
_, err := sa.allocateAsk(request)
@@ -1172,7 +1173,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
log.Log(log.SchedApplication).Warn("allocation of ask failed unexpectedly",
zap.Error(err))
}
- return alloc
+ return result
}
}
}
@@ -1183,7 +1184,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
}
// we checked all placeholders and asks nothing worked as yet
// pick the first fit and try all nodes if that fails give up
- var allocResult *Allocation
+ var allocResult *AllocationResult
if phFit != nil && reqFit != nil {
iterator.ForEachNode(func(node *Node) bool {
if !node.IsSchedulable() {
@@ -1206,7 +1207,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
alloc.SetRelease(phFit)
// placeholder point to the real one in the releases list
phFit.SetRelease(alloc)
- alloc.SetResultType(Replaced)
+ result := newReplacedAllocationResult(node.NodeID, reqFit, alloc)
// mark placeholder as released
phFit.SetReleased(true)
// update just the node to make sure we keep its spot
@@ -1224,7 +1225,7 @@ func (sa *Application) tryPlaceholderAllocate(nodeIterator func() NodeIterator,
zap.Error(err))
}
- allocResult = alloc
+ allocResult = result
return false
})
}
@@ -1239,7 +1240,7 @@ func (sa *Application) checkHeadRooms(ask *AllocationAsk, userHeadroom *resource
}
// Try a reserved allocation of an outstanding reservation
-func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIterator func() NodeIterator) *Allocation {
+func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIterator func() NodeIterator) *AllocationResult {
sa.Lock()
defer sa.Unlock()
// calculate the users' headroom, includes group check which requires the applicationID
@@ -1262,8 +1263,7 @@ func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIte
unreserveAsk = ask
}
// remove the reservation as this should not be reserved
- alloc := newUnreservedAllocation(reserve.nodeID, unreserveAsk)
- return alloc
+ return newUnreservedAllocationResult(reserve.nodeID, unreserveAsk)
}
if !sa.checkHeadRooms(ask, userHeadroom, headRoom) {
@@ -1278,16 +1278,16 @@ func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIte
}
}
// check allocation possibility
- alloc := sa.tryNode(reserve.node, ask)
+ result := sa.tryNode(reserve.node, ask)
// allocation worked fix the resultType and return
- if alloc != nil {
- alloc.SetResultType(AllocatedReserved)
- return alloc
+ if result != nil {
+ result.ResultType = AllocatedReserved
+ return result
}
}
- // lets try this on all other nodes
+ // try this on all other nodes
for _, reserve := range sa.reservations {
// Other nodes cannot be tried if the ask has a required node
ask := reserve.ask
@@ -1299,17 +1299,17 @@ func (sa *Application) tryReservedAllocate(headRoom *resources.Resource, nodeIte
if !sa.checkHeadRooms(ask, userHeadroom, headRoom) {
continue
}
- alloc := sa.tryNodesNoReserve(ask, iterator, reserve.nodeID)
+ result := sa.tryNodesNoReserve(ask, iterator, reserve.nodeID)
// have a candidate return it, including the node that was reserved
- if alloc != nil {
- return alloc
+ if result != nil {
+ return result
}
}
}
return nil
}
-func (sa *Application) tryPreemption(headRoom *resources.Resource, preemptionDelay time.Duration, ask *AllocationAsk, iterator NodeIterator, nodesTried bool) (*Allocation, bool) {
+func (sa *Application) tryPreemption(headRoom *resources.Resource, preemptionDelay time.Duration, ask *AllocationAsk, iterator NodeIterator, nodesTried bool) (*AllocationResult, bool) {
preemptor := NewPreemptor(sa, headRoom, preemptionDelay, ask, iterator, nodesTried)
// validate prerequisites for preemption of an ask and mark ask for preemption if successful
@@ -1358,9 +1358,9 @@ func (sa *Application) tryRequiredNodePreemption(reserve *reservation, ask *Allo
}
// Try all the nodes for a reserved request that have not been tried yet.
-// This should never resultType in a reservation as the ask is already reserved
-func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterator, reservedNode string) *Allocation {
- var allocResult *Allocation
+// This should never result in a reservation as the ask is already reserved
+func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterator, reservedNode string) *AllocationResult {
+ var allocResult *AllocationResult
iterator.ForEachNode(func(node *Node) bool {
if !node.IsSchedulable() {
log.Log(log.SchedApplication).Debug("skipping node for reserved ask as state is unschedulable",
@@ -1372,12 +1372,12 @@ func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterat
if !node.FitInNode(ask.GetAllocatedResource()) || node.NodeID == reservedNode {
return true
}
- alloc := sa.tryNode(node, ask)
+ result := sa.tryNode(node, ask)
// allocation worked: update resultType and return
- if alloc != nil {
- alloc.SetReservedNodeID(reservedNode)
- alloc.SetResultType(AllocatedReserved)
- allocResult = alloc
+ if result != nil {
+ result.ResultType = AllocatedReserved
+ result.ReservedNodeID = reservedNode
+ allocResult = result
return false
}
@@ -1389,14 +1389,14 @@ func (sa *Application) tryNodesNoReserve(ask *AllocationAsk, iterator NodeIterat
// Try all the nodes for a request. The resultType is an allocation or reservation of a node.
// New allocations can only be reserved after a delay.
-func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allocation {
+func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *AllocationResult {
var nodeToReserve *Node
scoreReserved := math.Inf(1)
// check if the ask is reserved or not
allocKey := ask.GetAllocationKey()
reservedAsks := sa.GetAskReservations(allocKey)
allowReserve := !ask.IsAllocated() && len(reservedAsks) == 0
- var allocResult *Allocation
+ var allocResult *AllocationResult
iterator.ForEachNode(func(node *Node) bool {
// skip the node if the node is not valid for the ask
if !node.IsSchedulable() {
@@ -1410,9 +1410,9 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
return true
}
tryNodeStart := time.Now()
- alloc := sa.tryNode(node, ask)
+ result := sa.tryNode(node, ask)
// allocation worked so return
- if alloc != nil {
+ if result != nil {
metrics.GetSchedulerMetrics().ObserveTryNodeLatency(tryNodeStart)
// check if the node was reserved for this ask: if it is set the resultType and return
// NOTE: this is a safeguard as reserved nodes should never be part of the iterator
@@ -1422,8 +1422,8 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
zap.String("appID", sa.ApplicationID),
zap.String("nodeID", node.NodeID),
zap.String("allocationKey", allocKey))
- alloc.SetResultType(AllocatedReserved)
- allocResult = alloc
+ result.ResultType = AllocatedReserved
+ allocResult = result
return false
}
// we could also have a different node reserved for this ask if it has pick one of
@@ -1434,13 +1434,13 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
zap.String("appID", sa.ApplicationID),
zap.String("nodeID", nodeID),
zap.String("allocationKey", allocKey))
- alloc.SetResultType(AllocatedReserved)
- alloc.SetReservedNodeID(nodeID)
- allocResult = alloc
+ result.ResultType = AllocatedReserved
+ result.ReservedNodeID = nodeID
+ allocResult = result
return false
}
// nothing reserved just return this as a normal alloc
- allocResult = alloc
+ allocResult = result
return false
}
// nothing allocated should we look at a reservation?
@@ -1479,15 +1479,14 @@ func (sa *Application) tryNodes(ask *AllocationAsk, iterator NodeIterator) *Allo
return nil
}
// return reservation allocation and mark it as a reservation
- alloc := newReservedAllocation(nodeToReserve.NodeID, ask)
- return alloc
+ return newReservedAllocationResult(nodeToReserve.NodeID, ask)
}
// ask does not fit, skip to next ask
return nil
}
// Try allocating on one specific node
-func (sa *Application) tryNode(node *Node, ask *AllocationAsk) *Allocation {
+func (sa *Application) tryNode(node *Node, ask *AllocationAsk) *AllocationResult {
toAllocate := ask.GetAllocatedResource()
// create the key for the reservation
if !node.preAllocateCheck(toAllocate, reservationKey(nil, sa, ask)) {
@@ -1516,8 +1515,9 @@ func (sa *Application) tryNode(node *Node, ask *AllocationAsk) *Allocation {
zap.Error(err))
}
// all is OK, last update for the app
- sa.addAllocationInternal(alloc)
- return alloc
+ result := newAllocatedAllocationResult(node.NodeID, ask, alloc)
+ sa.addAllocationInternal(result.ResultType, alloc)
+ return result
}
return nil
}
@@ -1616,17 +1616,17 @@ func (sa *Application) getAllRequestsInternal() []*AllocationAsk {
}
// Add a new Allocation to the application
-func (sa *Application) AddAllocation(info *Allocation) {
+func (sa *Application) AddAllocation(alloc *Allocation) {
sa.Lock()
defer sa.Unlock()
- sa.addAllocationInternal(info)
+ sa.addAllocationInternal(Allocated, alloc)
}
// Add the Allocation to the application
// No locking must be called while holding the lock
-func (sa *Application) addAllocationInternal(info *Allocation) {
+func (sa *Application) addAllocationInternal(allocType AllocationResultType, alloc *Allocation) {
// placeholder allocations do not progress the state of the app and are tracked in a separate total
- if info.IsPlaceholder() {
+ if alloc.IsPlaceholder() {
// when we have the first placeholder allocation start the placeholder timer.
// It will start to use the resources only after the first allocation, so we will count the time from this point.
// Also this is the first stable point on the placeholder handling, what is easy to explain and troubleshoot
@@ -1637,8 +1637,8 @@ func (sa *Application) addAllocationInternal(info *Allocation) {
sa.initPlaceholderTimer()
}
// User resource usage needs to be updated even during resource allocation happen for ph's itself even though state change would happen only after all ph allocation completes.
- sa.incUserResourceUsage(info.GetAllocatedResource())
- sa.allocatedPlaceholder = resources.Add(sa.allocatedPlaceholder, info.GetAllocatedResource())
+ sa.incUserResourceUsage(alloc.GetAllocatedResource())
+ sa.allocatedPlaceholder = resources.Add(sa.allocatedPlaceholder, alloc.GetAllocatedResource())
sa.maxAllocatedResource = resources.ComponentWiseMax(sa.allocatedPlaceholder, sa.maxAllocatedResource)
// If there are no more placeholder to allocate we should move state
@@ -1654,7 +1654,7 @@ func (sa *Application) addAllocationInternal(info *Allocation) {
// already when the last placeholder was allocated
// special case COMPLETING: gang with only one placeholder moves to COMPLETING and causes orphaned
// allocations
- if info.GetResultType() != Replaced || !resources.IsZero(sa.allocatedResource) || sa.IsCompleting() {
+ if allocType != Replaced || !resources.IsZero(sa.allocatedResource) || sa.IsCompleting() {
// progress the state based on where we are, we should never fail in this case
// keep track of a failure in log.
if err := sa.HandleApplicationEvent(RunApplication); err != nil {
@@ -1663,12 +1663,12 @@ func (sa *Application) addAllocationInternal(info *Allocation) {
zap.Error(err))
}
}
- sa.incUserResourceUsage(info.GetAllocatedResource())
- sa.allocatedResource = resources.Add(sa.allocatedResource, info.GetAllocatedResource())
+ sa.incUserResourceUsage(alloc.GetAllocatedResource())
+ sa.allocatedResource = resources.Add(sa.allocatedResource, alloc.GetAllocatedResource())
sa.maxAllocatedResource = resources.ComponentWiseMax(sa.allocatedResource, sa.maxAllocatedResource)
}
- sa.appEvents.sendNewAllocationEvent(info)
- sa.allocations[info.GetAllocationKey()] = info
+ sa.appEvents.sendNewAllocationEvent(alloc)
+ sa.allocations[alloc.GetAllocationKey()] = alloc
}
// Increase user resource usage
@@ -1735,11 +1735,10 @@ func (sa *Application) ReplaceAllocation(allocationKey string) *Allocation {
alloc.SetPlaceholderUsed(true)
alloc.SetPlaceholderCreateTime(ph.GetCreateTime())
alloc.SetBindTime(time.Now())
- sa.addAllocationInternal(alloc)
+ sa.addAllocationInternal(Replaced, alloc)
// order is important: clean up the allocation after adding it to the app
// we need the original Replaced allocation resultType.
alloc.ClearRelease()
- alloc.SetResultType(Allocated)
if sa.placeholderData != nil {
sa.placeholderData[ph.GetTaskGroup()].Replaced++
}
diff --git a/pkg/scheduler/objects/application_test.go b/pkg/scheduler/objects/application_test.go
index 7ab670a5..6a942c29 100644
--- a/pkg/scheduler/objects/application_test.go
+++ b/pkg/scheduler/objects/application_test.go
@@ -960,7 +960,6 @@ func TestGangAllocChange(t *testing.T) {
// add a real alloc this should NOT trigger state update
alloc = newAllocation(appID1, nodeID1, res)
- alloc.SetResultType(Replaced)
app.AddAllocation(alloc)
assert.Equal(t, len(app.GetAllAllocations()), 3)
assert.Assert(t, app.IsRunning(), "app should still be in running state")
@@ -968,7 +967,6 @@ func TestGangAllocChange(t *testing.T) {
// add a second real alloc this should NOT trigger state update
alloc = newAllocation(appID1, nodeID1, res)
- alloc.SetResultType(Replaced)
app.AddAllocation(alloc)
assert.Equal(t, len(app.GetAllAllocations()), 4)
assert.Assert(t, app.IsRunning(), "app should still be in running state")
@@ -1271,7 +1269,6 @@ func TestReplaceAllocation(t *testing.T) {
// set the real one to replace the placeholder
realAlloc := newAllocation(appID1, nodeID1, res)
- realAlloc.SetResultType(Replaced)
ph.SetRelease(realAlloc)
alloc = app.ReplaceAllocation(ph.GetAllocationKey())
assert.Equal(t, alloc, ph, "returned allocation is not the placeholder")
@@ -1290,27 +1287,6 @@ func TestReplaceAllocation(t *testing.T) {
app.addPlaceholderDataWithLocking(ph.GetAsk())
assert.Equal(t, app.placeholderData[""].Count, int64(3))
assertUserGroupResource(t, getTestUserGroup(), resources.Multiply(res, 2))
-
- // set multiple real allocations to replace the placeholder
- realAlloc = newAllocation(appID1, nodeID1, res)
- realAlloc.SetResultType(Replaced)
- ph.SetRelease(realAlloc)
- realAllocNoAdd := newAllocation(appID1, nodeID1, res)
- realAllocNoAdd.SetResultType(Replaced)
- ph.SetRelease(realAlloc)
- alloc = app.ReplaceAllocation(ph.GetAllocationKey())
- assert.Equal(t, alloc, ph, "returned allocation is not the placeholder")
- assert.Assert(t, resources.IsZero(app.allocatedPlaceholder), "real allocation counted as placeholder")
- assert.Equal(t, app.placeholderData[""].Replaced, int64(2))
- // after the second replace we have 2 real allocations
- if !resources.Equals(app.allocatedResource, resources.Multiply(res, 2)) {
- t.Fatalf("real allocation not updated as expected: got %s, expected %s", app.allocatedResource, resources.Multiply(res, 2))
- }
- assert.Equal(t, realAlloc.GetPlaceholderCreateTime(), ph.GetCreateTime(), "real allocation's placeholder create time not updated as expected: got %s, expected %s", realAlloc.GetPlaceholderCreateTime(), ph.GetCreateTime())
- if _, ok := app.allocations["not-added"]; ok {
- t.Fatalf("real allocation added which shouldn't have been added")
- }
- assertUserGroupResource(t, getTestUserGroup(), resources.Multiply(res, 2))
}
func TestReplaceAllocationTracking(t *testing.T) {
@@ -1345,21 +1321,18 @@ func TestReplaceAllocationTracking(t *testing.T) {
// replace placeholders
realAlloc1 := newAllocation(appID1, nodeID1, res)
- realAlloc1.SetResultType(Replaced)
ph1.SetRelease(realAlloc1)
alloc1 := app.ReplaceAllocation(ph1.GetAllocationKey())
app.RemoveAllocation(ph1.GetAllocationKey(), si.TerminationType_PLACEHOLDER_REPLACED)
assert.Equal(t, ph1.GetAllocationKey(), alloc1.GetAllocationKey())
assert.Equal(t, true, app.HasPlaceholderAllocation())
realAlloc2 := newAllocation(appID1, nodeID1, res)
- realAlloc2.SetResultType(Replaced)
ph2.SetRelease(realAlloc2)
alloc2 := app.ReplaceAllocation(ph2.GetAllocationKey())
app.RemoveAllocation(ph2.GetAllocationKey(), si.TerminationType_PLACEHOLDER_REPLACED)
assert.Equal(t, ph2.GetAllocationKey(), alloc2.GetAllocationKey())
assert.Equal(t, true, app.HasPlaceholderAllocation())
realAlloc3 := newAllocation(appID1, nodeID1, res)
- realAlloc3.SetResultType(Replaced)
ph3.SetRelease(realAlloc3)
alloc3 := app.ReplaceAllocation(ph3.GetAllocationKey())
app.RemoveAllocation(ph3.GetAllocationKey(), si.TerminationType_PLACEHOLDER_REPLACED)
@@ -1781,8 +1754,8 @@ func TestTryAllocateNoRequests(t *testing.T) {
app := newApplication(appID1, "default", "root.unknown")
preemptionAttemptsRemaining := 0
- alloc := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
- assert.Check(t, alloc == nil, "unexpected alloc")
+ result := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Check(t, result == nil, "unexpected result")
}
func TestTryAllocateFit(t *testing.T) {
@@ -1806,9 +1779,11 @@ func TestTryAllocateFit(t *testing.T) {
assert.NilError(t, err)
preemptionAttemptsRemaining := 0
- alloc := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
- assert.Assert(t, alloc != nil, "alloc expected")
- assert.Equal(t, "node1", alloc.GetNodeID(), "wrong node")
+ result := app.tryAllocate(node.GetAvailableResource(), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+
+ assert.Assert(t, result != nil, "alloc expected")
+ assert.Assert(t, result.Allocation != nil, "alloc expected")
+ assert.Equal(t, "node1", result.NodeID, "wrong node")
}
func TestTryAllocatePreemptQueue(t *testing.T) {
@@ -1848,20 +1823,24 @@ func TestTryAllocatePreemptQueue(t *testing.T) {
preemptionAttemptsRemaining := 10
- alloc1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ result1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result1 != nil, "result1 expected")
+ alloc1 := result1.Allocation
assert.Assert(t, alloc1 != nil, "alloc1 expected")
- alloc2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 5}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ result2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 5}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result2 != nil, "result2 expected")
+ alloc2 := result2.Allocation
assert.Assert(t, alloc2 != nil, "alloc2 expected")
// on first attempt, not enough time has passed
- alloc3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
- assert.Assert(t, alloc3 == nil, "alloc3 not expected")
+ result3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result3 == nil, "result3 not expected")
assert.Assert(t, !alloc2.IsPreempted(), "alloc2 should not have been preempted")
// pass the time and try again
ask3.createTime = ask3.createTime.Add(-30 * time.Second)
- alloc3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
- assert.Assert(t, alloc3 != nil && alloc3.resultType == Reserved, "alloc3 should be a reservation")
+ result3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 0}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result3 != nil && result3.Allocation == nil && result3.ResultType == Reserved, "alloc3 should be a reservation")
assert.Assert(t, alloc2.IsPreempted(), "alloc2 should have been preempted")
}
@@ -1916,31 +1895,44 @@ func TestTryAllocatePreemptNode(t *testing.T) {
preemptionAttemptsRemaining := 10
// consume capacity with 'unlimited' app
- alloc00 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 40}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ result00 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 40}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result00 != nil, "result00 expected")
+ alloc00 := result00.Allocation
assert.Assert(t, alloc00 != nil, "alloc00 expected")
- alloc01 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 39}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ result01 := app0.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 39}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result01 != nil, "result01 expected")
+ alloc01 := result01.Allocation
assert.Assert(t, alloc01 != nil, "alloc01 expected")
// consume remainder of space but not quota
- alloc1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 28}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ result1 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 28}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result1 != nil, "result1 expected")
+ alloc1 := result1.Allocation
assert.Assert(t, alloc1 != nil, "alloc1 expected")
- alloc2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 23}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ result2 := app1.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 23}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result2 != nil, "result2 expected")
+ alloc2 := result2.Allocation
assert.Assert(t, alloc2 != nil, "alloc2 expected")
// on first attempt, should see a reservation since we're after the reservation timeout
ask3.createTime = ask3.createTime.Add(-10 * time.Second)
- alloc3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
- assert.Assert(t, alloc3 != nil, "alloc3 expected")
- assert.Equal(t, "node1", alloc3.GetNodeID(), "wrong node assignment")
- assert.Equal(t, Reserved, alloc3.GetResultType(), "expected reservation")
+ result3 := app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result3 != nil, "result3 expected")
+ alloc3 := result3.Allocation
+ assert.Assert(t, alloc3 == nil, "alloc3 not expected")
+ assert.Equal(t, "node1", result3.NodeID, "wrong node assignment")
+ assert.Equal(t, Reserved, result3.ResultType, "expected reservation")
assert.Assert(t, !alloc2.IsPreempted(), "alloc2 should not have been preempted")
err = node1.Reserve(app2, ask3)
assert.NilError(t, err)
// pass the time and try again
ask3.createTime = ask3.createTime.Add(-30 * time.Second)
- alloc3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
- assert.Assert(t, alloc3 != nil, "alloc3 expected")
+ result3 = app2.tryAllocate(resources.NewResourceFromMap(map[string]resources.Quantity{"first": 18}), true, 30*time.Second, &preemptionAttemptsRemaining, iterator, iterator, getNode)
+ assert.Assert(t, result3 != nil, "result3 expected")
+ assert.Equal(t, Reserved, result3.ResultType, "expected reservation")
+ alloc3 = result3.Allocation
+ assert.Assert(t, alloc3 == nil, "alloc3 not expected")
assert.Assert(t, alloc1.IsPreempted(), "alloc1 should have been preempted")
}
@@ -2610,8 +2602,8 @@ func TestTryAllocateWithReservedHeadRoomChecking(t *testing.T) {
assert.NilError(t, err, "reservation should not have failed")
iter := getNodeIteratorFn(node1, node2)
- alloc := app.tryReservedAllocate(headRoom, iter)
- assert.Assert(t, alloc == nil, "Alloc is expected to be nil due to insufficient headroom")
+ result := app.tryReservedAllocate(headRoom, iter)
+ assert.Assert(t, result == nil, "result is expected to be nil due to insufficient headroom")
}
func TestUpdateRunnableStatus(t *testing.T) {
diff --git a/pkg/scheduler/objects/preemption.go b/pkg/scheduler/objects/preemption.go
index f006a0ed..d91dbe32 100644
--- a/pkg/scheduler/objects/preemption.go
+++ b/pkg/scheduler/objects/preemption.go
@@ -551,7 +551,7 @@ func (p *Preemptor) tryNodes() (string, []*Allocation, bool) {
return "", nil, false
}
-func (p *Preemptor) TryPreemption() (*Allocation, bool) {
+func (p *Preemptor) TryPreemption() (*AllocationResult, bool) {
// validate that sufficient capacity can be freed
if !p.checkPreemptionQueueGuarantees() {
return nil, false
@@ -649,7 +649,7 @@ func (p *Preemptor) TryPreemption() (*Allocation, bool) {
zap.String("allocationKey", p.ask.GetAllocationKey()),
zap.String("nodeID", nodeID),
zap.Int("victimCount", len(victims)))
- return newReservedAllocation(nodeID, p.ask), true
+ return newReservedAllocationResult(nodeID, p.ask), true
}
type predicateCheckResult struct {
diff --git a/pkg/scheduler/objects/preemption_test.go b/pkg/scheduler/objects/preemption_test.go
index bba1a9c2..d98de242 100644
--- a/pkg/scheduler/objects/preemption_test.go
+++ b/pkg/scheduler/objects/preemption_test.go
@@ -221,10 +221,11 @@ func TestTryPreemption(t *testing.T) {
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.NilError(t, plugin.GetPredicateError())
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
+ assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
assert.Check(t, alloc1.IsPreempted(), "alloc1 not preempted")
assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
}
@@ -283,10 +284,11 @@ func TestTryPreemptionOnNode(t *testing.T) {
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID2, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID2, result.NodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
}
@@ -344,10 +346,11 @@ func TestTryPreemptionOnQueue(t *testing.T) {
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID2, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID2, result.NodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
}
@@ -398,10 +401,9 @@ func TestTryPreemption_VictimsAvailable_InsufficientResource(t *testing.T) {
headRoom := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10, "pods": 3})
preemptor := NewPreemptor(app2, headRoom, 30*time.Second, ask3, iterator(), false)
- alloc, ok := preemptor.TryPreemption()
- var expectedAlloc *Allocation
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result == nil, "unexpected result")
assert.Equal(t, ok, false, "no victims found")
- assert.Equal(t, alloc, expectedAlloc, "wrong alloc")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
}
@@ -462,10 +464,9 @@ func TestTryPreemption_VictimsOnDifferentNodes_InsufficientResource(t *testing.T
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
- var expectedAlloc *Allocation
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result == nil, "unexpected result")
assert.Equal(t, ok, false, "no victims found")
- assert.Equal(t, alloc, expectedAlloc, "wrong alloc")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
}
@@ -525,10 +526,9 @@ func TestTryPreemption_VictimsAvailableOnDifferentNodes(t *testing.T) {
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
- var expectedAlloc *Allocation
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result == nil, "unexpected result")
assert.Equal(t, ok, false, "no victims found")
- assert.Equal(t, alloc, expectedAlloc, "wrong alloc")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
assert.Check(t, !alloc2.IsPreempted(), "alloc2 preempted")
}
@@ -606,10 +606,11 @@ func TestTryPreemption_OnQueue_VictimsOnDifferentNodes(t *testing.T) {
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID2, alloc.nodeID, "wrong alloc")
+ assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID2, result.NodeID, "wrong alloc")
assert.Equal(t, nodeID1, alloc1.nodeID, "wrong node")
assert.Equal(t, nodeID2, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID2, alloc4.nodeID, "wrong node")
@@ -691,10 +692,11 @@ func TestTryPreemption_OnQueue_VictimsAvailable_LowerPriority(t *testing.T) {
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc1.nodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID2, alloc4.nodeID, "wrong node")
@@ -763,10 +765,11 @@ func TestTryPreemption_AskResTypesDifferent_GuaranteedSetOnPreemptorSide(t *test
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
@@ -831,10 +834,11 @@ func TestTryPreemption_OnNode_AskResTypesDifferent_GuaranteedSetOnPreemptorSide(
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc3", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc3", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
assert.Check(t, alloc2.IsPreempted(), "alloc2 not preempted")
@@ -929,11 +933,12 @@ func TestTryPreemption_AskResTypesDifferent_GuaranteedSetOnVictimAndPreemptorSid
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.NilError(t, plugin.GetPredicateError())
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1029,11 +1034,12 @@ func TestTryPreemption_OnNode_AskResTypesDifferent_GuaranteedSetOnVictimAndPreem
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
assert.NilError(t, plugin.GetPredicateError())
+ assert.Assert(t, result != nil, "no result")
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1130,11 +1136,12 @@ func TestTryPreemption_AskResTypesSame_GuaranteedSetOnPreemptorSide(t *testing.T
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.NilError(t, plugin.GetPredicateError())
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1230,11 +1237,12 @@ func TestTryPreemption_OnNode_AskResTypesSame_GuaranteedSetOnPreemptorSide(t *te
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.NilError(t, plugin.GetPredicateError())
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1332,11 +1340,12 @@ func TestTryPreemption_AskResTypesSame_GuaranteedSetOnVictimAndPreemptorSides(t
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.NilError(t, plugin.GetPredicateError())
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
@@ -1433,11 +1442,12 @@ func TestTryPreemption_OnNode_AskResTypesSame_GuaranteedSetOnVictimAndPreemptorS
plugins.RegisterSchedulerPlugin(plugin)
defer plugins.UnregisterSchedulerPlugins()
- alloc, ok := preemptor.TryPreemption()
+ result, ok := preemptor.TryPreemption()
+ assert.Assert(t, result != nil, "no result")
assert.NilError(t, plugin.GetPredicateError())
assert.Assert(t, ok, "no victims found")
- assert.Equal(t, "alloc4", alloc.allocationKey, "wrong alloc")
- assert.Equal(t, nodeID1, alloc.nodeID, "wrong node")
+ assert.Equal(t, "alloc4", result.Ask.GetAllocationKey(), "wrong alloc")
+ assert.Equal(t, nodeID1, result.NodeID, "wrong node")
assert.Equal(t, nodeID1, alloc2.nodeID, "wrong node")
assert.Equal(t, nodeID1, alloc3.nodeID, "wrong node")
assert.Check(t, !alloc1.IsPreempted(), "alloc1 preempted")
diff --git a/pkg/scheduler/objects/queue.go b/pkg/scheduler/objects/queue.go
index ff4957e7..9960d01a 100644
--- a/pkg/scheduler/objects/queue.go
+++ b/pkg/scheduler/objects/queue.go
@@ -1324,7 +1324,7 @@ func (sq *Queue) canRunApp(appID string) bool {
// resources are skipped.
// Applications are sorted based on the application sortPolicy. Applications without pending resources are skipped.
// Lock free call this all locks are taken when needed in called functions
-func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() NodeIterator, getnode func(string) *Node, allowPreemption bool) *Allocation {
+func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() NodeIterator, getnode func(string) *Node, allowPreemption bool) *AllocationResult {
if sq.IsLeafQueue() {
// get the headroom
headRoom := sq.getHeadRoom()
@@ -1339,26 +1339,27 @@ func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() N
if app.IsAccepted() && (!runnableInQueue || !runnableByUserLimit) {
continue
}
- alloc := app.tryAllocate(headRoom, allowPreemption, preemptionDelay, &preemptAttemptsRemaining, iterator, fullIterator, getnode)
- if alloc != nil {
+ result := app.tryAllocate(headRoom, allowPreemption, preemptionDelay, &preemptAttemptsRemaining, iterator, fullIterator, getnode)
+ if result != nil {
log.Log(log.SchedQueue).Info("allocation found on queue",
zap.String("queueName", sq.QueuePath),
zap.String("appID", app.ApplicationID),
- zap.Stringer("allocation", alloc))
+ zap.Stringer("resultType", result.ResultType),
+ zap.Stringer("allocation", result.Allocation))
// if the app is still in Accepted state we're allocating placeholders.
// we want to count these apps as running
if app.IsAccepted() {
sq.setAllocatingAccepted(app.ApplicationID)
}
- return alloc
+ return result
}
}
} else {
// process the child queues (filters out queues without pending requests)
for _, child := range sq.sortQueues() {
- alloc := child.TryAllocate(iterator, fullIterator, getnode, allowPreemption)
- if alloc != nil {
- return alloc
+ result := child.TryAllocate(iterator, fullIterator, getnode, allowPreemption)
+ if result != nil {
+ return result
}
}
}
@@ -1371,25 +1372,26 @@ func (sq *Queue) TryAllocate(iterator func() NodeIterator, fullIterator func() N
// the configured queue sortPolicy. Queues without pending resources are skipped.
// Applications are sorted based on the application sortPolicy. Applications without pending resources are skipped.
// Lock free call this all locks are taken when needed in called functions
-func (sq *Queue) TryPlaceholderAllocate(iterator func() NodeIterator, getnode func(string) *Node) *Allocation {
+func (sq *Queue) TryPlaceholderAllocate(iterator func() NodeIterator, getnode func(string) *Node) *AllocationResult {
if sq.IsLeafQueue() {
// process the apps (filters out app without pending requests)
for _, app := range sq.sortApplications(true) {
- alloc := app.tryPlaceholderAllocate(iterator, getnode)
- if alloc != nil {
+ result := app.tryPlaceholderAllocate(iterator, getnode)
+ if result != nil {
log.Log(log.SchedQueue).Info("allocation found on queue",
zap.String("queueName", sq.QueuePath),
zap.String("appID", app.ApplicationID),
- zap.Stringer("allocation", alloc))
- return alloc
+ zap.Stringer("resultType", result.ResultType),
+ zap.Stringer("allocation", result.Allocation))
+ return result
}
}
} else {
// process the child queues (filters out queues without pending requests)
for _, child := range sq.sortQueues() {
- alloc := child.TryPlaceholderAllocate(iterator, getnode)
- if alloc != nil {
- return alloc
+ result := child.TryPlaceholderAllocate(iterator, getnode)
+ if result != nil {
+ return result
}
}
}
@@ -1420,7 +1422,7 @@ func (sq *Queue) GetQueueOutstandingRequests(total *[]*AllocationAsk) {
// the configured queue sortPolicy. Queues without pending resources are skipped.
// Applications are currently NOT sorted and are iterated over in a random order.
// Lock free call this all locks are taken when needed in called functions
-func (sq *Queue) TryReservedAllocate(iterator func() NodeIterator) *Allocation {
+func (sq *Queue) TryReservedAllocate(iterator func() NodeIterator) *AllocationResult {
if sq.IsLeafQueue() {
// skip if it has no reservations
reservedCopy := sq.GetReservedApps()
@@ -1444,28 +1446,29 @@ func (sq *Queue) TryReservedAllocate(iterator func() NodeIterator) *Allocation {
if app.IsAccepted() && (!sq.canRunApp(appID) || !ugm.GetUserManager().CanRunApp(sq.QueuePath, appID, app.user)) {
continue
}
- alloc := app.tryReservedAllocate(headRoom, iterator)
- if alloc != nil {
+ result := app.tryReservedAllocate(headRoom, iterator)
+ if result != nil {
log.Log(log.SchedQueue).Info("reservation found for allocation found on queue",
zap.String("queueName", sq.QueuePath),
zap.String("appID", appID),
- zap.Stringer("allocation", alloc),
+ zap.Stringer("resultType", result.ResultType),
+ zap.Stringer("allocation", result.Allocation),
zap.String("appStatus", app.CurrentState()))
// if the app is still in Accepted state we're allocating placeholders.
// we want to count these apps as running
if app.IsAccepted() {
sq.setAllocatingAccepted(app.ApplicationID)
}
- return alloc
+ return result
}
}
}
} else {
// process the child queues (filters out queues that have no pending requests)
for _, child := range sq.sortQueues() {
- alloc := child.TryReservedAllocate(iterator)
- if alloc != nil {
- return alloc
+ result := child.TryReservedAllocate(iterator)
+ if result != nil {
+ return result
}
}
}
diff --git a/pkg/scheduler/partition.go b/pkg/scheduler/partition.go
index 8ede0725..01e0f39a 100644
--- a/pkg/scheduler/partition.go
+++ b/pkg/scheduler/partition.go
@@ -829,22 +829,22 @@ func (pc *PartitionContext) calculateOutstandingRequests() []*objects.Allocation
// Try regular allocation for the partition
// Lock free call this all locks are taken when needed in called functions
-func (pc *PartitionContext) tryAllocate() *objects.Allocation {
+func (pc *PartitionContext) tryAllocate() *objects.AllocationResult {
if !resources.StrictlyGreaterThanZero(pc.root.GetPendingResource()) {
// nothing to do just return
return nil
}
// try allocating from the root down
- alloc := pc.root.TryAllocate(pc.GetNodeIterator, pc.GetFullNodeIterator, pc.GetNode, pc.isPreemptionEnabled())
- if alloc != nil {
- return pc.allocate(alloc)
+ result := pc.root.TryAllocate(pc.GetNodeIterator, pc.GetFullNodeIterator, pc.GetNode, pc.isPreemptionEnabled())
+ if result != nil {
+ return pc.allocate(result)
}
return nil
}
// Try process reservations for the partition
// Lock free call this all locks are taken when needed in called functions
-func (pc *PartitionContext) tryReservedAllocate() *objects.Allocation {
+func (pc *PartitionContext) tryReservedAllocate() *objects.AllocationResult {
if pc.getReservationCount() == 0 {
return nil
}
@@ -853,16 +853,16 @@ func (pc *PartitionContext) tryReservedAllocate() *objects.Allocation {
return nil
}
// try allocating from the root down
- alloc := pc.root.TryReservedAllocate(pc.GetNodeIterator)
- if alloc != nil {
- return pc.allocate(alloc)
+ result := pc.root.TryReservedAllocate(pc.GetNodeIterator)
+ if result != nil {
+ return pc.allocate(result)
}
return nil
}
// Try process placeholder for the partition
// Lock free call this all locks are taken when needed in called functions
-func (pc *PartitionContext) tryPlaceholderAllocate() *objects.Allocation {
+func (pc *PartitionContext) tryPlaceholderAllocate() *objects.AllocationResult {
if pc.getPhAllocationCount() == 0 {
return nil
}
@@ -871,23 +871,23 @@ func (pc *PartitionContext) tryPlaceholderAllocate() *objects.Allocation {
return nil
}
// try allocating from the root down
- alloc := pc.root.TryPlaceholderAllocate(pc.GetNodeIterator, pc.GetNode)
- if alloc != nil {
+ result := pc.root.TryPlaceholderAllocate(pc.GetNodeIterator, pc.GetNode)
+ if result != nil {
log.Log(log.SchedPartition).Info("scheduler replace placeholder processed",
- zap.String("appID", alloc.GetApplicationID()),
- zap.String("allocationKey", alloc.GetAllocationKey()),
- zap.String("placeholder released allocationKey", alloc.GetRelease().GetAllocationKey()))
+ zap.String("appID", result.Ask.GetApplicationID()),
+ zap.String("allocationKey", result.Ask.GetAllocationKey()),
+ zap.String("placeholder released allocationKey", result.Allocation.GetRelease().GetAllocationKey()))
// pass the release back to the RM via the cluster context
- return alloc
+ return result
}
return nil
}
// Process the allocation and make the left over changes in the partition.
// NOTE: this is a lock free call. It must NOT be called holding the PartitionContext lock.
-func (pc *PartitionContext) allocate(alloc *objects.Allocation) *objects.Allocation {
+func (pc *PartitionContext) allocate(result *objects.AllocationResult) *objects.AllocationResult {
// find the app make sure it still exists
- appID := alloc.GetApplicationID()
+ appID := result.Ask.GetApplicationID()
app := pc.getApplication(appID)
if app == nil {
log.Log(log.SchedPartition).Info("Application was removed while allocating",
@@ -898,12 +898,13 @@ func (pc *PartitionContext) allocate(alloc *objects.Allocation) *objects.Allocat
// if the node was passed in use that ID instead of the one from the allocation
// the node ID is set when a reservation is allocated on a non-reserved node
var nodeID string
- if alloc.GetReservedNodeID() == "" {
- nodeID = alloc.GetNodeID()
+ alloc := result.Allocation
+ if alloc == nil || result.ReservedNodeID == "" {
+ nodeID = result.NodeID
} else {
- nodeID = alloc.GetReservedNodeID()
+ nodeID = result.ReservedNodeID
log.Log(log.SchedPartition).Debug("Reservation allocated on different node",
- zap.String("current node", alloc.GetNodeID()),
+ zap.String("current node", result.NodeID),
zap.String("reserved node", nodeID),
zap.String("appID", appID))
}
@@ -914,36 +915,37 @@ func (pc *PartitionContext) allocate(alloc *objects.Allocation) *objects.Allocat
zap.String("appID", appID))
return nil
}
- alloc.SetInstanceType(node.GetInstanceType())
// reservation
- if alloc.GetResultType() == objects.Reserved {
- pc.reserve(app, node, alloc.GetAsk())
+ if result.ResultType == objects.Reserved {
+ pc.reserve(app, node, result.Ask)
return nil
}
// unreserve
- if alloc.GetResultType() == objects.Unreserved || alloc.GetResultType() == objects.AllocatedReserved {
- pc.unReserve(app, node, alloc.GetAsk())
- if alloc.GetResultType() == objects.Unreserved {
+ if result.ResultType == objects.Unreserved || result.ResultType == objects.AllocatedReserved {
+ pc.unReserve(app, node, result.Ask)
+ if result.ResultType == objects.Unreserved {
return nil
}
// remove the link to the reserved node
- alloc.SetReservedNodeID("")
+ result.ReservedNodeID = ""
}
+ alloc.SetInstanceType(node.GetInstanceType())
+
// track the number of allocations
pc.updateAllocationCount(1)
- if alloc.IsPlaceholder() {
+ if result.Ask.IsPlaceholder() {
pc.incPhAllocationCount()
}
log.Log(log.SchedPartition).Info("scheduler allocation processed",
- zap.String("appID", alloc.GetApplicationID()),
- zap.String("allocationKey", alloc.GetAllocationKey()),
- zap.Stringer("allocatedResource", alloc.GetAllocatedResource()),
- zap.Bool("placeholder", alloc.IsPlaceholder()),
+ zap.String("appID", result.Ask.GetApplicationID()),
+ zap.String("allocationKey", result.Ask.GetAllocationKey()),
+ zap.Stringer("allocatedResource", result.Ask.GetAllocatedResource()),
+ zap.Bool("placeholder", result.Ask.IsPlaceholder()),
zap.String("targetNode", alloc.GetNodeID()))
- // pass the allocation back to the RM via the cluster context
- return alloc
+ // pass the allocation result back to the RM via the cluster context
+ return result
}
// Process the reservation in the scheduler
diff --git a/pkg/scheduler/partition_test.go b/pkg/scheduler/partition_test.go
index 003a0387..7a014c4a 100644
--- a/pkg/scheduler/partition_test.go
+++ b/pkg/scheduler/partition_test.go
@@ -374,7 +374,6 @@ func TestRemoveNodeWithPlaceholders(t *testing.T) {
alloc.SetRelease(ph)
// double link as if the replacement is ongoing
ph.SetRelease(alloc)
- alloc.SetResultType(objects.Replaced)
allocs = app.GetAllAllocations()
assert.Equal(t, len(allocs), 1, "expected one allocation for the app (placeholder)")
@@ -488,8 +487,8 @@ func TestPlaceholderDataWithPlaceholderPreemption(t *testing.T) {
err = gangApp.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask %s to app1", lastPh)
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- assert.Assert(t, ph != nil, "expected placeholder to be allocated")
+ result := partition.tryAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "expected placeholder to be allocated")
}
assert.Equal(t, 7, partition.GetTotalAllocationCount(), "placeholder allocation should be counted as normal allocations on the partition")
assert.Equal(t, 6, partition.getPhAllocationCount(), "placeholder allocations should be counted as placeholders on the partition")
@@ -511,8 +510,8 @@ func TestPlaceholderDataWithPlaceholderPreemption(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-2 to app1-1")
// since node-2 available resource is less than needed, reserve the node
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result := partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation attempt should not have returned an allocation")
}
// check if updated (must be after allocate call)
@@ -520,8 +519,8 @@ func TestPlaceholderDataWithPlaceholderPreemption(t *testing.T) {
assert.Equal(t, 1, len(app2.GetAskReservations(allocKey2)), "ask should have been reserved")
// try through reserved scheduling cycle this should trigger preemption
- alloc = partition.tryReservedAllocate()
- if alloc != nil {
+ result = partition.tryReservedAllocate()
+ if result != nil {
t.Fatal("reserved allocation attempt should not have returned an allocation")
}
@@ -612,8 +611,8 @@ func TestPlaceholderDataWithNodeRemoval(t *testing.T) {
err = gangApp.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app1")
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- if ph == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected placeholder to be allocated")
}
}
@@ -696,11 +695,11 @@ func TestPlaceholderDataWithRemoval(t *testing.T) {
err = gangApp.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app1")
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- if ph == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected placeholder to be allocated")
}
- lastPhAllocationKey = ph.GetAllocationKey()
+ lastPhAllocationKey = result.Allocation.GetAllocationKey()
}
// add an ask for a last placeholder and allocate
@@ -774,7 +773,6 @@ func TestRemoveNodeWithReplacement(t *testing.T) {
// add real allocation that is replacing the placeholder on the 2nd node
alloc := objects.NewAllocation(nodeID2, ask)
alloc.SetRelease(ph)
- alloc.SetResultType(objects.Replaced)
node2.AddAllocation(alloc)
allocated = node2.GetAllAllocations()
assert.Equal(t, 1, len(allocated), "allocation not added correctly to node2")
@@ -801,7 +799,6 @@ func TestRemoveNodeWithReplacement(t *testing.T) {
allocs = app.GetAllAllocations()
assert.Equal(t, 1, len(allocs), "expected one allocation for the app (real)")
assert.Equal(t, alloc.GetAllocationKey(), allocs[0].GetAllocationKey(), "allocationKey for the app is not the same as the real allocation")
- assert.Equal(t, objects.Allocated, allocs[0].GetResultType(), "allocation result type should be allocated")
assert.Check(t, !allocs[0].HasRelease(), "real allocation should not have release liked anymore")
assertLimits(t, getTestUserGroup(), appRes)
}
@@ -846,7 +843,6 @@ func TestRemoveNodeWithReal(t *testing.T) {
// add real allocation that is replacing the placeholder on the 2nd node
alloc := objects.NewAllocation(nodeID2, ask)
alloc.SetRelease(ph)
- alloc.SetResultType(objects.Replaced)
node2.AddAllocation(alloc)
allocated = node2.GetAllAllocations()
assert.Equal(t, 1, len(allocated), "allocation not added correctly to node2")
@@ -1535,8 +1531,8 @@ func TestTryAllocate(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
// create a set of queues and apps: app-1 2 asks; app-2 1 ask (same size)
@@ -1573,36 +1569,36 @@ func TestTryAllocate(t *testing.T) {
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), nil, expectedQueuesMaxLimits)
// first allocation should be app-1 and alloc-2
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.Multiply(res, 1), expectedQueuesMaxLimits)
// second allocation should be app-2 and alloc-1: higher up in the queue hierarchy
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID2, "expected application app-2 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID2, "expected application app-2 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.Multiply(res, 2), expectedQueuesMaxLimits)
// third allocation should be app-1 and alloc-1
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
assert.Assert(t, resources.IsZero(partition.root.GetPendingResource()), "pending resources should be set to zero")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.Multiply(res, 3), expectedQueuesMaxLimits)
}
@@ -1614,8 +1610,8 @@ func TestRequiredNodeReservation(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
app := newApplication(appID1, "default", "root.parent.sub-leaf")
@@ -1632,23 +1628,23 @@ func TestRequiredNodeReservation(t *testing.T) {
assertLimits(t, getTestUserGroup(), nil)
// first allocation should be app-1 and alloc-1
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
assertLimits(t, getTestUserGroup(), res)
ask2 := newAllocationAsk(allocKey2, appID1, res)
ask2.SetRequiredNode(nodeID1)
err = app.AddAllocationAsk(ask2)
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
- alloc = partition.tryAllocate()
- if alloc != nil {
- t.Fatal("allocation attempt should have returned an allocation")
+ result = partition.tryAllocate()
+ if result != nil {
+ t.Fatal("allocation attempt should not have returned an allocation")
}
// check if updated (must be after allocate call)
assert.Equal(t, 1, len(app.GetReservations()), "app should have one reserved ask")
@@ -1664,8 +1660,8 @@ func TestRequiredNodeReservation(t *testing.T) {
ask3.SetRequiredNode(nodeID1)
err = app.AddAllocationAsk(ask3)
assert.NilError(t, err, "failed to add ask alloc-3 to app-1")
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation attempt should not have returned an allocation")
}
@@ -1680,8 +1676,8 @@ func TestRequiredNodeCancelNonDSReservations(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
// override the reservation delay, and cleanup when done
@@ -1712,15 +1708,15 @@ func TestRequiredNodeCancelNonDSReservations(t *testing.T) {
assert.Assert(t, resources.Equals(res, partition.root.GetPendingResource()), "pending resource not set as expected on root queue")
// the first one should be allocated
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("1st allocation did not return the correct allocation")
}
- assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+ assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
// the second one should be reserved as the 2nd node is not scheduling
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("2nd allocation did not return the correct allocation")
}
// check if updated (must be after allocate call)
@@ -1741,11 +1737,11 @@ func TestRequiredNodeCancelNonDSReservations(t *testing.T) {
err = app1.AddAllocationAsk(ask2)
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("1st allocation did not return the correct allocation")
}
- assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+ assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
// earlier app (app1) reservation count should be zero
assert.Equal(t, 0, len(app.GetReservations()), "ask should have been reserved")
@@ -1758,8 +1754,8 @@ func TestRequiredNodeCancelDSReservations(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
// override the reservation delay, and cleanup when done
@@ -1792,15 +1788,15 @@ func TestRequiredNodeCancelDSReservations(t *testing.T) {
assert.Assert(t, resources.Equals(res, partition.root.GetPendingResource()), "pending resource not set as expected on root queue")
// the first one should be allocated
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("1st allocation did not return the correct allocation")
}
- assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+ assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
// the second one should be reserved as the 2nd node is not scheduling
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("2nd allocation should not return allocation")
}
// check if updated (must be after allocate call)
@@ -1821,8 +1817,8 @@ func TestRequiredNodeCancelDSReservations(t *testing.T) {
err = app1.AddAllocationAsk(ask2)
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("3rd allocation should not return allocation")
}
// still reservation count is 1
@@ -1836,8 +1832,8 @@ func TestRequiredNodeNotExist(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
// add app to the partition
@@ -1860,8 +1856,8 @@ func TestRequiredNodeNotExist(t *testing.T) {
t.Fatal("panic on nil required node")
}
}()
- alloc := partition.tryAllocate()
- if alloc != nil {
+ result := partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation should not have worked on unknown node")
}
assertLimits(t, getTestUserGroup(), nil)
@@ -1873,8 +1869,8 @@ func TestRequiredNodeAllocation(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result.Allocation.String())
}
app := newApplication(appID1, "default", "root.parent.sub-leaf")
@@ -1891,14 +1887,14 @@ func TestRequiredNodeAllocation(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
// first allocation should be app-1 and alloc-1
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
assertLimits(t, getTestUserGroup(), res)
// required node set on ask
@@ -1908,14 +1904,14 @@ func TestRequiredNodeAllocation(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
// since node-1 available resource is larger than required ask gets allocated
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
// ensure there is no reservations
assert.Equal(t, 0, len(app.GetReservations()), "ask should not have been reserved")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
assertLimits(t, getTestUserGroup(), resources.Multiply(res, 2))
}
@@ -1955,8 +1951,8 @@ func TestPreemption(t *testing.T) {
time.Sleep(time.Second)
// third allocation should not succeed, as we are currently above capacity
- alloc := partition.tryAllocate()
- if alloc != nil {
+ result := partition.tryAllocate()
+ if result != nil {
t.Fatal("unexpected allocation")
}
@@ -1966,8 +1962,8 @@ func TestPreemption(t *testing.T) {
// allocation should still not do anything as we have not yet released the preempted allocation
// but the ask should have a reservation
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("unexpected allocation")
}
@@ -1989,13 +1985,13 @@ func TestPreemption(t *testing.T) {
assert.Assert(t, resources.IsZero(preemptingRes), "incorrect preempting resources")
// allocation should now allocate
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("missing allocation")
}
assert.Equal(t, 0, len(app2.GetReservations()), "ask should not be reserved")
- assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type should be allocated from reservation")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey3, "expected ask alloc-3 to be allocated")
+ assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type should be allocated from reservation")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey3, "expected ask alloc-3 to be allocated")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 10000}), getExpectedQueuesLimitsForPreemption())
appSummary := app1.GetApplicationSummary("default")
@@ -2011,9 +2007,9 @@ func TestPreemptionForRequiredNodeNormalAlloc(t *testing.T) {
// setup the partition so we can try the real allocation
partition, app := setupPreemptionForRequiredNode(t)
// now try the allocation again: the normal path
- alloc := partition.tryAllocate()
- if alloc != nil {
- t.Fatal("allocations should not have returned an allocation")
+ result := partition.tryAllocate()
+ if result != nil {
+ t.Fatal("allocations should not have returned a result")
}
// check if updated (must be after allocate call)
assert.Equal(t, 1, len(app.GetReservations()), "ask should have been reserved")
@@ -2025,15 +2021,15 @@ func TestPreemptionForRequiredNodeReservedAlloc(t *testing.T) {
// setup the partition so we can try the real allocation
partition, app := setupPreemptionForRequiredNode(t)
// now try the allocation again: the reserved path
- alloc := partition.tryReservedAllocate()
- if alloc == nil {
+ result := partition.tryReservedAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation attempt should have returned an allocation")
}
// check if updated (must be after allocate call)
assert.Equal(t, 0, len(app.GetReservations()), "ask should have no longer be reserved")
- assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type is not the expected AllocatedReserved")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+ assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type is not the expected AllocatedReserved")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}), getExpectedQueuesLimitsForPreemption())
}
@@ -2057,7 +2053,9 @@ func TestPreemptionForRequiredNodeMultipleAttemptsAvoided(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
// first allocation should be app-1 and alloc-1
- alloc := partition.tryAllocate()
+ result := partition.tryAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "alloc expected")
+ alloc := result.Allocation
// required node set on ask
ask2 := newAllocationAsk(allocKey2, appID1, res)
@@ -2122,8 +2120,8 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
app1, _ := newApplicationWithHandler(appID1, "default", "root.parent.leaf1")
@@ -2140,15 +2138,15 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
// first allocation should be app-1 and alloc-1
- alloc1 := partition.tryAllocate()
- if alloc1 == nil {
+ result1 := partition.tryAllocate()
+ if result1 == nil || result1.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc1.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc1.HasRelease(), "released allocation should not be present")
- assert.Equal(t, alloc1.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc1.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
- assert.Equal(t, alloc1.GetNodeID(), nodeID1, "expected alloc-1 on node-1")
+ assert.Equal(t, result1.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result1.Allocation.HasRelease(), "released allocation should not be present")
+ assert.Equal(t, result1.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result1.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result1.NodeID, nodeID1, "expected alloc-1 on node-1")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 5000}), getExpectedQueuesLimitsForPreemption())
@@ -2158,15 +2156,15 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
// second allocation should be app-1 and alloc-2
- alloc2 := partition.tryAllocate()
- if alloc2 == nil {
+ result2 := partition.tryAllocate()
+ if result2 == nil || result2.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc2.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc2.HasRelease(), "released allocation should not be present")
- assert.Equal(t, alloc2.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc2.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
- assert.Equal(t, alloc2.GetNodeID(), nodeID2, "expected alloc-2 on node-2")
+ assert.Equal(t, result2.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result2.Allocation.HasRelease(), "released allocation should not be present")
+ assert.Equal(t, result2.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result2.Allocation.GetAllocationKey(), allocKey2, "expected ask alloc-2 to be allocated")
+ assert.Equal(t, result2.NodeID, nodeID2, "expected alloc-2 on node-2")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 10000}), getExpectedQueuesLimitsForPreemption())
app2, _ := newApplicationWithHandler(appID2, "default", "root.parent.leaf2")
@@ -2175,7 +2173,7 @@ func setupPreemption(t *testing.T) (*PartitionContext, *objects.Application, *ob
err = partition.AddApplication(app2)
assert.NilError(t, err, "failed to add app-1 to partition")
- return partition, app1, app2, alloc1, alloc2
+ return partition, app1, app2, result1.Allocation, result2.Allocation
}
// setup the partition in a state that we need for multiple tests
@@ -2184,8 +2182,8 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
app, testHandler := newApplicationWithHandler(appID1, "default", "root.parent.sub-leaf")
@@ -2202,16 +2200,16 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
// first allocation should be app-1 and alloc-1
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}), getExpectedQueuesLimitsForPreemptionWithRequiredNode())
- allocationKey := alloc.GetAllocationKey()
+ allocationKey := result.Allocation.GetAllocationKey()
// required node set on ask
ask2 := newAllocationAsk(allocKey2, appID1, res)
@@ -2220,8 +2218,8 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
// since node-1 available resource is less than needed, reserve the node for alloc-2
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation attempt should not have returned an allocation")
}
// check if updated (must be after allocate call)
@@ -2230,8 +2228,8 @@ func setupPreemptionForRequiredNode(t *testing.T) (*PartitionContext, *objects.A
assertUserGroupResourceMaxLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}), getExpectedQueuesLimitsForPreemptionWithRequiredNode())
// try through reserved scheduling cycle this should trigger preemption
- alloc = partition.tryReservedAllocate()
- if alloc != nil {
+ result = partition.tryReservedAllocate()
+ if result != nil {
t.Fatal("reserved allocation attempt should not have returned an allocation")
}
@@ -2263,8 +2261,8 @@ func TestTryAllocateLarge(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
// override the reservation delay, and cleanup when done
@@ -2282,9 +2280,9 @@ func TestTryAllocateLarge(t *testing.T) {
err = app.AddAllocationAsk(newAllocationAsk("alloc-1", appID1, res))
assert.NilError(t, err, "failed to add large ask to app")
assert.Assert(t, resources.Equals(res, app.GetPendingResource()), "pending resource not set as expected")
- alloc := partition.tryAllocate()
- if alloc != nil {
- t.Fatalf("allocation did return allocation which does not fit: %s", alloc)
+ result := partition.tryAllocate()
+ if result != nil {
+ t.Fatalf("allocation returned unexpected result: %s", result)
}
assert.Equal(t, 0, len(app.GetReservations()), "ask should not have been reserved")
assertLimits(t, getTestUserGroup(), nil)
@@ -2296,8 +2294,8 @@ func TestAllocReserveNewNode(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned result: %s", result)
}
// override the reservation delay, and cleanup when done
@@ -2328,16 +2326,16 @@ func TestAllocReserveNewNode(t *testing.T) {
assert.Assert(t, resources.Equals(res, partition.root.GetPendingResource()), "pending resource not set as expected on root queue")
// the first one should be allocated
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("1st allocation did not return the correct allocation")
}
- assert.Equal(t, objects.Allocated, alloc.GetResultType(), "allocation result type should have been allocated")
+ assert.Equal(t, objects.Allocated, result.ResultType, "allocation result type should have been allocated")
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 8000}))
// the second one should be reserved as the 2nd node is not scheduling
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("2nd allocation did not return the correct allocation")
}
// check if updated (must be after allocate call)
@@ -2346,10 +2344,11 @@ func TestAllocReserveNewNode(t *testing.T) {
// turn on 2nd node
node2.SetSchedulable(true)
- alloc = partition.tryReservedAllocate()
- assert.Equal(t, objects.AllocatedReserved, alloc.GetResultType(), "allocation result type should have been allocatedReserved")
- assert.Equal(t, "", alloc.GetReservedNodeID(), "reserved node should be reset after processing")
- assert.Equal(t, node2.NodeID, alloc.GetNodeID(), "allocation should be fulfilled on new node")
+ result = partition.tryReservedAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "no result")
+ assert.Equal(t, objects.AllocatedReserved, result.ResultType, "allocation result type should have been allocatedReserved")
+ assert.Equal(t, "", result.ReservedNodeID, "reserved node should be reset after processing")
+ assert.Equal(t, node2.NodeID, result.NodeID, "allocation should be fulfilled on new node")
// check if all updated
node1 := partition.GetNode(nodeID1)
assert.Equal(t, 0, len(node1.GetReservationKeys()), "old node should have no more reservations")
@@ -2363,8 +2362,8 @@ func TestTryAllocateReserve(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryReservedAllocate(); alloc != nil {
- t.Fatalf("empty cluster reserved allocate returned allocation: %s", alloc)
+ if result := partition.tryReservedAllocate(); result != nil {
+ t.Fatalf("empty cluster reserved allocate returned allocation: %s", result)
}
// create a set of queues and apps: app-1 2 asks; app-2 1 ask (same size)
@@ -2394,15 +2393,15 @@ func TestTryAllocateReserve(t *testing.T) {
}
// first allocation should be app-1 and alloc-2
- alloc := partition.tryReservedAllocate()
- if alloc == nil {
+ result := partition.tryReservedAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type is not the expected allocated from reserved")
- assert.Equal(t, alloc.GetReservedNodeID(), "", "node should not be set for allocated from reserved")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
+ assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type is not the expected allocated from reserved")
+ assert.Equal(t, result.ReservedNodeID, "", "node should not be set for allocated from reserved")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 1000}))
// reservations should have been removed: it is in progress
@@ -2411,19 +2410,19 @@ func TestTryAllocateReserve(t *testing.T) {
}
// no reservations left this should return nil
- alloc = partition.tryReservedAllocate()
- if alloc != nil {
- t.Fatalf("reserved allocation should not return any allocation: %s, '%s'", alloc, alloc.GetReservedNodeID())
+ result = partition.tryReservedAllocate()
+ if result != nil {
+ t.Fatalf("reserved allocation should not return any allocation: %s", result)
}
// try non reserved this should allocate
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not be present")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), "alloc-1", "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not be present")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), "alloc-1", "expected ask alloc-1 to be allocated")
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 2000}))
if !resources.IsZero(partition.root.GetPendingResource()) {
@@ -2465,23 +2464,23 @@ func TestTryAllocateWithReserved(t *testing.T) {
if !app.IsReservedOnNode(node2.NodeID) || len(app.GetAskReservations("alloc-1")) == 0 {
t.Fatal("reservation failure for ask and node2")
}
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return correct an allocation")
}
- assert.Equal(t, objects.AllocatedReserved, alloc.GetResultType(), "expected reserved allocation to be returned")
- assert.Equal(t, "", alloc.GetReservedNodeID(), "reserved node should be reset after processing")
+ assert.Equal(t, objects.AllocatedReserved, result.ResultType, "expected reserved allocation to be returned")
+ assert.Equal(t, "", result.ReservedNodeID, "reserved node should be reset after processing")
assert.Equal(t, 0, len(node2.GetReservationKeys()), "reservation should have been removed from node")
assert.Equal(t, false, app.IsReservedOnNode(node2.NodeID), "reservation cleanup for ask on app failed")
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 5000}))
// node2 is unreserved now so the next one should allocate on the 2nd node (fair sharing)
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return correct allocation")
}
- assert.Equal(t, objects.Allocated, alloc.GetResultType(), "expected allocated allocation to be returned")
- assert.Equal(t, node2.NodeID, alloc.GetNodeID(), "expected allocation on node2 to be returned")
+ assert.Equal(t, objects.Allocated, result.ResultType, "expected allocated allocation to be returned")
+ assert.Equal(t, node2.NodeID, result.NodeID, "expected allocation on node2 to be returned")
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 10000}))
}
@@ -2492,8 +2491,8 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %s", alloc)
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
// override the reservation delay, and cleanup when done
@@ -2517,9 +2516,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
// allocate the ask
for i := 1; i <= 4; i++ {
- alloc := partition.tryAllocate()
- if alloc == nil || alloc.GetResultType() != objects.Allocated {
- t.Fatalf("expected allocated allocation to be returned (step %d) %s", i, alloc)
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil || result.ResultType != objects.Allocated {
+ t.Fatalf("expected allocated allocation to be returned (step %d)", i)
}
}
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 16000}))
@@ -2535,9 +2534,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
assert.Assert(t, resources.Equals(pending, app.GetPendingResource()), "pending resource not set as expected")
// allocate so we get reservations
for i := 1; i <= 2; i++ {
- alloc := partition.tryAllocate()
- if alloc != nil {
- t.Fatalf("expected reservations to be created not allocation to be returned (step %d) %s", i, alloc)
+ result := partition.tryAllocate()
+ if result != nil {
+ t.Fatalf("expected reservations to be created not allocation to be returned (step %d) %s", i, result)
}
assert.Equal(t, len(app.GetReservations()), i, "application reservations incorrect")
}
@@ -2550,9 +2549,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
assert.NilError(t, err, "failed to add node node-3 to the partition")
// Try to allocate one of the reservation. We go directly to the root queue not using the partition otherwise
// we confirm before we get back in the test code and cannot remove the ask
- alloc := partition.root.TryReservedAllocate(partition.GetNodeIterator)
- if alloc == nil || alloc.GetResultType() != objects.AllocatedReserved {
- t.Fatalf("expected allocatedReserved allocation to be returned %v", alloc)
+ result := partition.root.TryReservedAllocate(partition.GetNodeIterator)
+ if result == nil || result.Allocation == nil || result.ResultType != objects.AllocatedReserved {
+ t.Fatalf("expected allocatedReserved allocation to be returned")
}
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 20000}))
@@ -2560,7 +2559,7 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
// shim in processAllocationReleaseByAllocationKey()
// make sure we are counting correctly and leave the other reservation intact
removeAskID := "alloc-5"
- if alloc.GetAllocationKey() == "alloc-6" {
+ if result.Allocation.GetAllocationKey() == "alloc-6" {
removeAskID = "alloc-6"
}
released := app.RemoveAllocationAsk(removeAskID)
@@ -2569,8 +2568,9 @@ func TestScheduleRemoveReservedAsk(t *testing.T) {
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 20000}))
// now confirm the allocation: this should not remove the reservation
- rmAlloc := partition.allocate(alloc)
- assert.Equal(t, "", rmAlloc.GetReservedNodeID(), "reserved node should be reset after processing")
+ rmAlloc := partition.allocate(result)
+ assert.Assert(t, rmAlloc != nil && rmAlloc.Allocation != nil, "no result")
+ assert.Equal(t, "", rmAlloc.ReservedNodeID, "reserved node should be reset after processing")
assert.Equal(t, len(app.GetReservations()), 1, "application reservations should be kept at 1")
assertLimits(t, getTestUserGroup(), resources.NewResourceFromMap(map[string]resources.Quantity{"vcore": 20000}))
}
@@ -2941,11 +2941,11 @@ func TestPlaceholderSmallerThanReal(t *testing.T) {
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- if ph == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected placeholder ph-1 to be allocated")
}
- assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+ assert.Equal(t, phID, result.Allocation.GetAllocationKey(), "expected allocation of ph-1 to be returned")
assert.Assert(t, resources.Equals(phRes, app.GetQueue().GetAllocatedResource()), "placeholder size should be allocated on queue")
assert.Assert(t, resources.Equals(phRes, node.GetAllocatedResource()), "placeholder size should be allocated on node")
assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered on the partition")
@@ -2959,14 +2959,14 @@ func TestPlaceholderSmallerThanReal(t *testing.T) {
if partition.tryPlaceholderAllocate() != nil {
t.Fatal("allocation should not have matched placeholder")
}
- assert.Assert(t, ph.IsReleased(), "placeholder should be released")
+ assert.Assert(t, result.Allocation.IsReleased(), "placeholder should be released")
assertLimits(t, getTestUserGroup(), phRes)
// release placeholder: do what the context would do after the shim processing
release := &si.AllocationRelease{
PartitionName: partition.Name,
ApplicationID: appID1,
- AllocationKey: ph.GetAllocationKey(),
+ AllocationKey: result.Allocation.GetAllocationKey(),
TerminationType: si.TerminationType_TIMEOUT,
}
assert.Equal(t, 1, partition.getPhAllocationCount(), "ph should be registered")
@@ -3006,12 +3006,12 @@ func TestPlaceholderSmallerMulti(t *testing.T) {
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask %s to app", id)
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- if ph == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatalf("expected placeholder %s to be allocated", id)
}
- assert.Equal(t, id, ph.GetAllocationKey(), "expected allocation of %s to be returned", id)
- phs[id] = ph
+ assert.Equal(t, id, result.Allocation.GetAllocationKey(), "expected allocation of %s to be returned", id)
+ phs[id] = result.Allocation
}
assert.Assert(t, resources.Equals(tgRes, app.GetQueue().GetAllocatedResource()), "all placeholders should be allocated on queue")
assert.Assert(t, resources.Equals(tgRes, node.GetAllocatedResource()), "all placeholders should be allocated on node")
@@ -3055,8 +3055,8 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
setupUGM()
partition, err := newBasePartition()
assert.NilError(t, err, "partition create failed")
- if alloc := partition.tryPlaceholderAllocate(); alloc != nil {
- t.Fatalf("empty cluster placeholder allocate returned allocation: %s", alloc)
+ if result := partition.tryPlaceholderAllocate(); result != nil {
+ t.Fatalf("empty cluster placeholder allocate returned allocation: %s", result)
}
tgRes := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 5, "second": 5})
@@ -3075,11 +3075,11 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- if ph == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected placeholder ph-1 to be allocated")
}
- assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+ assert.Equal(t, phID, result.Allocation.GetAllocationKey(), "expected allocation of ph-1 to be returned")
assert.Assert(t, resources.Equals(phRes, app.GetQueue().GetAllocatedResource()), "placeholder size should be allocated on queue")
assert.Assert(t, resources.Equals(phRes, node.GetAllocatedResource()), "placeholder size should be allocated on node")
assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered on the partition")
@@ -3090,12 +3090,12 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
ask = newAllocationAskTG(allocKey, appID1, taskGroup, smallRes, false)
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask alloc-1 to app with correct TG")
- alloc := partition.tryPlaceholderAllocate()
- if alloc == nil {
+ result2 := partition.tryPlaceholderAllocate()
+ if result2 == nil || result2.Allocation == nil {
t.Fatal("allocation should have matched placeholder")
}
- assert.Equal(t, objects.Replaced, alloc.GetResultType(), "expected replacement result type to be returned")
- assert.Check(t, alloc.HasRelease(), "placeholder should have been linked")
+ assert.Equal(t, objects.Replaced, result2.ResultType, "expected replacement result type to be returned")
+ assert.Check(t, result2.Allocation.HasRelease(), "placeholder should have been linked")
// no updates yet on queue and node
assert.Assert(t, resources.Equals(phRes, app.GetQueue().GetAllocatedResource()), "placeholder size should still be allocated on queue")
assert.Assert(t, resources.Equals(phRes, node.GetAllocatedResource()), "placeholder size should still be allocated on node")
@@ -3105,7 +3105,7 @@ func TestPlaceholderBiggerThanReal(t *testing.T) {
release := &si.AllocationRelease{
PartitionName: partition.Name,
ApplicationID: appID1,
- AllocationKey: ph.GetAllocationKey(),
+ AllocationKey: result.Allocation.GetAllocationKey(),
TerminationType: si.TerminationType_PLACEHOLDER_REPLACED,
}
released, confirmed := partition.removeAllocation(release)
@@ -3140,12 +3140,12 @@ func TestPlaceholderMatch(t *testing.T) {
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- if ph == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected placeholder ph-1 to be allocated")
}
- phAllocationKey := ph.GetAllocationKey()
- assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+ phAllocationKey := result.Allocation.GetAllocationKey()
+ assert.Equal(t, phID, phAllocationKey, "expected allocation of ph-1 to be returned")
assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should be created on allocate")
assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered as allocation")
assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
@@ -3155,13 +3155,13 @@ func TestPlaceholderMatch(t *testing.T) {
ask = newAllocationAskTG(allocKey, appID1, "unknown", phRes, false)
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask alloc-2 to app")
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected ask to be allocated (unmatched task group)")
}
assert.Equal(t, 2, partition.GetTotalAllocationCount(), "allocations should be registered: ph + normal")
assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
- assert.Equal(t, allocKey, alloc.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
+ assert.Equal(t, allocKey, result.Allocation.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should not be updated")
assert.Equal(t, int64(1), app.GetAllPlaceholderData()[0].Count, "placeholder data should show 1 available placeholder")
assert.Equal(t, int64(0), app.GetAllPlaceholderData()[0].Replaced, "placeholder data should show no replacements")
@@ -3171,8 +3171,8 @@ func TestPlaceholderMatch(t *testing.T) {
ask = newAllocationAskTG(allocKey2, appID1, taskGroup, phRes, false)
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask alloc-2 to app")
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("expected ask not to be allocated (matched task group)")
}
assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should not be updated")
@@ -3181,13 +3181,13 @@ func TestPlaceholderMatch(t *testing.T) {
assertLimits(t, getTestUserGroup(), resources.Multiply(phRes, 2))
// replace the placeholder should work
- alloc = partition.tryPlaceholderAllocate()
- if alloc == nil {
+ result = partition.tryPlaceholderAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation should have matched placeholder")
}
assert.Equal(t, 2, partition.GetTotalAllocationCount(), "allocations should be registered: ph + normal")
assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
- assert.Equal(t, allocKey2, alloc.GetAllocationKey(), "expected allocation of alloc-2 to be returned")
+ assert.Equal(t, allocKey2, result.Allocation.GetAllocationKey(), "expected allocation of alloc-2 to be returned")
assert.Equal(t, int64(1), app.GetAllPlaceholderData()[0].Count, "placeholder data should show 1 available placeholder")
assert.Equal(t, int64(0), app.GetAllPlaceholderData()[0].Replaced, "placeholder data should show no replacements yet")
@@ -3213,8 +3213,8 @@ func TestPlaceholderMatch(t *testing.T) {
ask = newAllocationAskTG("no_ph_used", appID1, taskGroup, phRes, false)
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask no_ph_used to app")
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected ask to be allocated no placeholders left")
}
assertLimits(t, getTestUserGroup(), resources.Multiply(phRes, 3))
@@ -3241,12 +3241,13 @@ func TestPreemptedPlaceholderSkip(t *testing.T) {
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
// try to allocate a placeholder via normal allocate
- ph := partition.tryAllocate()
- if ph == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected placeholder ph-1 to be allocated")
}
- phAllocationKey := ph.GetAllocationKey()
- assert.Equal(t, phID, ph.GetAllocationKey(), "expected allocation of ph-1 to be returned")
+ ph := result.Allocation
+ phAllocationKey := result.Allocation.GetAllocationKey()
+ assert.Equal(t, phID, phAllocationKey, "expected allocation of ph-1 to be returned")
assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should be created on allocate")
assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder allocation should be registered as allocation")
assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder allocation should be registered")
@@ -3264,8 +3265,8 @@ func TestPreemptedPlaceholderSkip(t *testing.T) {
ph.MarkPreempted()
// replace the placeholder should NOT work
- alloc = partition.tryPlaceholderAllocate()
- if alloc != nil {
+ result = partition.tryPlaceholderAllocate()
+ if result != nil {
t.Fatal("allocation should not have matched placeholder")
}
@@ -3286,11 +3287,11 @@ func TestPreemptedPlaceholderSkip(t *testing.T) {
assert.Equal(t, 0, partition.getPhAllocationCount(), "no placeholder allocation should be registered")
// normal allocate should work as we have no placeholders left
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected ask to be allocated (no placeholder left)")
}
- assert.Equal(t, allocKey, alloc.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
+ assert.Equal(t, allocKey, result.Allocation.GetAllocationKey(), "expected allocation of alloc-1 to be returned")
assert.Equal(t, 1, len(app.GetAllPlaceholderData()), "placeholder data should not be updated")
assert.Equal(t, int64(1), app.GetAllPlaceholderData()[0].Count, "placeholder data should show 1 available placeholder")
assert.Equal(t, int64(0), app.GetAllPlaceholderData()[0].Replaced, "placeholder data should show no replacements")
@@ -3304,8 +3305,8 @@ func TestTryPlaceholderAllocate(t *testing.T) {
setupUGM()
partition, err := newBasePartition()
assert.NilError(t, err, "partition create failed")
- if alloc := partition.tryPlaceholderAllocate(); alloc != nil {
- t.Fatalf("empty cluster placeholder allocate returned allocation: %s", alloc)
+ if result := partition.tryPlaceholderAllocate(); result != nil {
+ t.Fatalf("empty cluster placeholder allocate returned allocation: %s", result)
}
var tgRes, res *resources.Resource
@@ -3326,19 +3327,19 @@ func TestTryPlaceholderAllocate(t *testing.T) {
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
// try to allocate placeholder should just return
- alloc := partition.tryPlaceholderAllocate()
- if alloc != nil {
- t.Fatalf("placeholder ask should not be allocated: %s", alloc)
+ result := partition.tryPlaceholderAllocate()
+ if result != nil {
+ t.Fatalf("placeholder ask should not be allocated: %s", result)
}
assertLimits(t, getTestUserGroup(), nil)
// try to allocate a placeholder via normal allocate
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected first placeholder to be allocated")
}
- assert.Equal(t, node.GetAllocation(alloc.GetAllocationKey()), alloc, "placeholder allocation not found on node")
- assert.Assert(t, alloc.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "placeholder alloc should return an allocated result")
+ assert.Equal(t, node.GetAllocation(result.Allocation.GetAllocationKey()), result.Allocation, "placeholder allocation not found on node")
+ assert.Assert(t, result.Allocation.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
+ assert.Equal(t, result.ResultType, objects.Allocated, "placeholder alloc should return an allocated result")
if !resources.Equals(app.GetPlaceholderResource(), res) {
t.Fatalf("placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), res)
}
@@ -3350,16 +3351,16 @@ func TestTryPlaceholderAllocate(t *testing.T) {
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add placeholder ask ph-2 to app")
// try to allocate placeholder should just return
- alloc = partition.tryPlaceholderAllocate()
- if alloc != nil {
- t.Fatalf("placeholder ask should not be allocated: %s", alloc)
+ result = partition.tryPlaceholderAllocate()
+ if result != nil {
+ t.Fatalf("placeholder ask should not be allocated: %s", result)
}
assertLimits(t, getTestUserGroup(), res)
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected 2nd placeholder to be allocated")
}
- assert.Equal(t, node.GetAllocation(alloc.GetAllocationKey()), alloc, "placeholder allocation 2 not found on node")
+ assert.Equal(t, node.GetAllocation(result.Allocation.GetAllocationKey()), result.Allocation, "placeholder allocation 2 not found on node")
if !resources.Equals(app.GetPlaceholderResource(), resources.Multiply(res, 2)) {
t.Fatalf("placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), resources.Multiply(res, 2))
}
@@ -3371,9 +3372,9 @@ func TestTryPlaceholderAllocate(t *testing.T) {
ask = newAllocationAskTG(allocKey, appID1, "tg-unk", res, false)
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask alloc-1 to app")
- alloc = partition.tryPlaceholderAllocate()
- if alloc != nil {
- t.Fatalf("allocation should not have matched placeholder: %s", alloc)
+ result = partition.tryPlaceholderAllocate()
+ if result != nil {
+ t.Fatalf("allocation should not have matched placeholder: %s", result)
}
assertLimits(t, getTestUserGroup(), resources.Multiply(res, 2))
@@ -3381,16 +3382,16 @@ func TestTryPlaceholderAllocate(t *testing.T) {
ask = newAllocationAskTG(allocKey2, appID1, taskGroup, res, false)
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask alloc-2 to app with correct TG")
- alloc = partition.tryPlaceholderAllocate()
- if alloc == nil {
+ result = partition.tryPlaceholderAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation should have matched placeholder")
}
assert.Equal(t, 2, partition.GetTotalAllocationCount(), "placeholder replacement should not be counted as alloc")
assert.Equal(t, 2, partition.getPhAllocationCount(), "placeholder allocation should be registered")
- assert.Equal(t, alloc.GetResultType(), objects.Replaced, "result type is not the expected allocated replaced")
- assert.Check(t, alloc.HasRelease(), "released allocation should be present")
+ assert.Equal(t, result.ResultType, objects.Replaced, "result type is not the expected allocated replaced")
+ assert.Check(t, result.Allocation.HasRelease(), "released allocation should be present")
assertLimits(t, getTestUserGroup(), resources.Multiply(res, 2))
- phAllocationKey := alloc.GetRelease().GetAllocationKey()
+ phAllocationKey := result.Allocation.GetRelease().GetAllocationKey()
// placeholder is not released until confirmed by the shim
if !resources.Equals(app.GetPlaceholderResource(), resources.Multiply(res, 2)) {
t.Fatalf("placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), resources.Multiply(res, 2))
@@ -3410,7 +3411,7 @@ func TestTryPlaceholderAllocate(t *testing.T) {
if confirmed == nil {
t.Fatal("confirmed allocation should not be nil")
}
- assert.Equal(t, confirmed.GetAllocationKey(), alloc.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
+ assert.Equal(t, confirmed.GetAllocationKey(), result.Allocation.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
if !resources.Equals(app.GetPlaceholderResource(), res) {
t.Fatalf("placeholder allocations not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), res)
}
@@ -3425,8 +3426,8 @@ func TestFailReplacePlaceholder(t *testing.T) {
setupUGM()
partition, err := newBasePartition()
assert.NilError(t, err, "partition create failed")
- if alloc := partition.tryPlaceholderAllocate(); alloc != nil {
- t.Fatalf("empty cluster placeholder allocate returned allocation: %s", alloc)
+ if result := partition.tryPlaceholderAllocate(); result != nil {
+ t.Fatalf("empty cluster placeholder allocate returned allocation: %s", result)
}
// plugin to let the pre-check fail on node-1 only, means we cannot replace the placeholder
plugin := mock.NewPredicatePlugin(false, map[string]int{nodeID1: -1})
@@ -3454,16 +3455,16 @@ func TestFailReplacePlaceholder(t *testing.T) {
assert.NilError(t, err, "failed to add placeholder ask ph-1 to app")
// try to allocate a placeholder via normal allocate
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("expected first placeholder to be allocated")
}
assert.Equal(t, partition.GetTotalAllocationCount(), 1, "placeholder allocation should be counted as alloc")
assert.Equal(t, partition.getPhAllocationCount(), 1, "placeholder allocation should be counted as placeholder")
- assert.Equal(t, node.GetAllocation(alloc.GetAllocationKey()), alloc, "placeholder allocation not found on node")
- assert.Assert(t, alloc.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "placeholder alloc should return an allocated result type")
- assert.Equal(t, alloc.GetNodeID(), nodeID1, "should be allocated on node-1")
+ assert.Equal(t, node.GetAllocation(result.Allocation.GetAllocationKey()), result.Allocation, "placeholder allocation not found on node")
+ assert.Assert(t, result.Allocation.IsPlaceholder(), "placeholder alloc should return a placeholder allocation")
+ assert.Equal(t, result.ResultType, objects.Allocated, "placeholder alloc should return an allocated result type")
+ assert.Equal(t, result.NodeID, nodeID1, "should be allocated on node-1")
assert.Assert(t, resources.Equals(app.GetPlaceholderResource(), res), "placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), res)
assertLimits(t, getTestUserGroup(), res)
@@ -3474,21 +3475,21 @@ func TestFailReplacePlaceholder(t *testing.T) {
ask = newAllocationAskTG(allocKey, appID1, taskGroup, res, false)
err = app.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask alloc-1 to app with correct TG")
- alloc = partition.tryPlaceholderAllocate()
- if alloc == nil {
+ result = partition.tryPlaceholderAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation should have matched placeholder")
}
assert.Equal(t, partition.GetTotalAllocationCount(), 1, "placeholder replacement should not be counted as alloc")
assert.Equal(t, partition.getPhAllocationCount(), 1, "placeholder allocation should not change")
- assert.Equal(t, alloc.GetResultType(), objects.Replaced, "result type is not the expected allocated replaced")
- assert.Check(t, alloc.HasRelease(), "released allocation should be present")
+ assert.Equal(t, result.ResultType, objects.Replaced, "result type is not the expected allocated replaced")
+ assert.Check(t, result.Allocation.HasRelease(), "released allocation should be present")
// allocation must be added as it is on a different node
- assert.Equal(t, alloc.GetNodeID(), nodeID2, "should be allocated on node-2")
+ assert.Equal(t, result.NodeID, nodeID2, "should be allocated on node-2")
assert.Assert(t, resources.IsZero(app.GetAllocatedResource()), "allocated resources should be zero")
assert.Assert(t, resources.Equals(node.GetAllocatedResource(), res), "node-1 allocation not updated as expected: got %s, expected %s", node.GetAllocatedResource(), res)
assert.Assert(t, resources.Equals(node2.GetAllocatedResource(), res), "node-2 allocation not updated as expected: got %s, expected %s", node2.GetAllocatedResource(), res)
- phAllocationKey := alloc.GetRelease().GetAllocationKey()
+ phAllocationKey := result.Allocation.GetRelease().GetAllocationKey()
// placeholder is not released until confirmed by the shim
assert.Assert(t, resources.Equals(app.GetPlaceholderResource(), res), "placeholder allocation not updated as expected: got %s, expected %s", app.GetPlaceholderResource(), resources.Multiply(res, 2))
assertLimits(t, getTestUserGroup(), res)
@@ -3507,7 +3508,7 @@ func TestFailReplacePlaceholder(t *testing.T) {
if confirmed == nil {
t.Fatal("confirmed allocation should not be nil")
}
- assert.Equal(t, confirmed.GetAllocationKey(), alloc.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
+ assert.Equal(t, confirmed.GetAllocationKey(), result.Allocation.GetAllocationKey(), "confirmed allocation has unexpected AllocationKey")
assert.Assert(t, resources.IsZero(app.GetPlaceholderResource()), "placeholder resources should be zero")
assert.Assert(t, resources.Equals(app.GetAllocatedResource(), res), "allocations not updated as expected: got %s, expected %s", app.GetAllocatedResource(), res)
assert.Assert(t, resources.IsZero(node.GetAllocatedResource()), "node-1 allocated resources should be zero")
@@ -3732,8 +3733,8 @@ func TestTryAllocateMaxRunning(t *testing.T) {
if partition == nil {
t.Fatal("partition create failed")
}
- if alloc := partition.tryAllocate(); alloc != nil {
- t.Fatalf("empty cluster allocate returned allocation: %v", alloc.String())
+ if result := partition.tryAllocate(); result != nil {
+ t.Fatalf("empty cluster allocate returned allocation: %s", result)
}
// set max running apps
@@ -3757,14 +3758,14 @@ func TestTryAllocateMaxRunning(t *testing.T) {
assert.Equal(t, app.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
// allocate should work: app stays in accepted state (placeholder!)
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc to be allocated")
assert.Equal(t, app.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
// add second app to the partition
@@ -3775,41 +3776,41 @@ func TestTryAllocateMaxRunning(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-2")
// allocation should fail max running app is reached on parent via accepted allocating
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation should not have returned as parent limit is reached")
}
// allocate should work: app moves to Starting all placeholder allocated
err = app.AddAllocationAsk(newAllocationAskTG("alloc-2", appID1, "ph1", res, true))
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), "alloc-2", "expected ask alloc-2 to be allocated")
assert.Equal(t, app.CurrentState(), objects.Running.String(), "application should have moved to running state")
// allocation should still fail: max running apps on parent reached
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation should not have returned as parent limit is reached")
}
// update the parent queue max running
parent.SetMaxRunningApps(2)
// allocation works
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Check(t, !alloc.HasRelease(), "released allocation should not exist")
- assert.Equal(t, alloc.GetApplicationID(), appID2, "expected application app-2 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Check(t, !result.Allocation.HasRelease(), "released allocation should not exist")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID2, "expected application app-2 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
}
func TestNewQueueEvents(t *testing.T) {
@@ -3872,15 +3873,15 @@ func TestUserHeadroom(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-2")
// app 1 would be allocated as there is headroom available for the user
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
// app 2 allocation won't happen as there is no headroom for the user
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation should not happen")
}
@@ -3894,11 +3895,11 @@ func TestUserHeadroom(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-3")
// app 3 would be allocated as there is headroom available for the user
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
app4 := newApplication("app-4", "default", "root.leaf")
err = partition.AddApplication(app4)
@@ -3907,8 +3908,8 @@ func TestUserHeadroom(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-4")
// app 4 allocation won't happen as there is no headroom for the user
- alloc = partition.tryAllocate()
- if alloc != nil {
+ result = partition.tryAllocate()
+ if result != nil {
t.Fatal("allocation should not happen")
}
partition.removeApplication(appID1)
@@ -3937,19 +3938,19 @@ func TestUserHeadroom(t *testing.T) {
node1 := partition.GetNode(nodeID1)
node1.SetSchedulable(false)
- alloc = partition.tryReservedAllocate()
- if alloc == nil {
+ result = partition.tryReservedAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, objects.AllocatedReserved, alloc.GetResultType(), "allocation result type should have been allocated")
+ assert.Equal(t, objects.AllocatedReserved, result.ResultType, "allocation result type should have been allocated")
// create a reservation and ensure reservation has not been allocated because there is no headroom for the user
ask = newAllocationAsk("alloc-2", "app-5", res)
err = app5.AddAllocationAsk(ask)
assert.NilError(t, err, "failed to add ask to app")
partition.reserve(app5, node2, ask)
- alloc = partition.tryReservedAllocate()
- if alloc != nil {
+ result = partition.tryReservedAllocate()
+ if result != nil {
t.Fatal("allocation should not happen on other nodes as well")
}
partition.removeApplication("app-5")
@@ -3967,11 +3968,11 @@ func TestUserHeadroom(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-6")
// app 6 would be allocated as headroom is nil because no limits configured for 'testuser1' user an
- alloc = partition.tryAllocate()
- if alloc == nil {
+ result = partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
}
func TestPlaceholderAllocationTracking(t *testing.T) {
@@ -4002,26 +4003,26 @@ func TestPlaceholderAllocationTracking(t *testing.T) {
assert.NilError(t, err, "failed to add ask to app")
// allocate first placeholder
- alloc := partition.tryAllocate()
- ph1AllocationKey := alloc.GetAllocationKey()
- assert.Assert(t, alloc != nil, "placeholder ask should have been allocated")
+ result := partition.tryAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "placeholder ask should have been allocated")
+ ph1AllocationKey := result.Allocation.GetAllocationKey()
assert.Equal(t, 1, partition.GetTotalAllocationCount(), "placeholder not counted as alloc")
assert.Equal(t, 1, partition.getPhAllocationCount(), "placeholder not counted as placeholder")
- alloc1 := partition.tryPlaceholderAllocate()
- assert.Assert(t, alloc1 != nil, "ask should have been allocated")
+ result1 := partition.tryPlaceholderAllocate()
+ assert.Assert(t, result1 != nil && result1.Allocation != nil, "ask should have been allocated")
assert.Equal(t, 1, partition.GetTotalAllocationCount(), "should see no change in alloc count")
assert.Equal(t, 1, partition.getPhAllocationCount(), "should see no change in placeholder count")
// allocate second placeholder
- alloc = partition.tryAllocate()
- ph2AllocationKey := alloc.GetAllocationKey()
- assert.Assert(t, alloc != nil, "placeholder ask should have been allocated")
+ result = partition.tryAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "placeholder ask should have been allocated")
+ ph2AllocationKey := result.Allocation.GetAllocationKey()
assert.Equal(t, 2, partition.GetTotalAllocationCount(), "placeholder not counted as alloc")
assert.Equal(t, 2, partition.getPhAllocationCount(), "placeholder not counted as placeholder")
// allocate third placeholder
- alloc = partition.tryAllocate()
- ph3AllocationKey := alloc.GetAllocationKey()
- assert.Assert(t, alloc != nil, "placeholder ask should have been allocated")
+ result = partition.tryAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "placeholder ask should have been allocated")
+ ph3AllocationKey := result.Allocation.GetAllocationKey()
assert.Equal(t, 3, partition.GetTotalAllocationCount(), "placeholder not counted as alloc")
assert.Equal(t, 3, partition.getPhAllocationCount(), "placeholder not counted as placeholder")
@@ -4068,13 +4069,14 @@ func TestReservationTracking(t *testing.T) {
err = app.AddAllocationAsk(ask2)
assert.NilError(t, err, "failed to add ask")
- alloc := partition.tryAllocate() // ask1 occupies node1
- allocationKey := alloc.GetAllocationKey()
- assert.Equal(t, objects.Allocated, alloc.GetResultType())
- assert.Equal(t, "alloc-1", alloc.GetAllocationKey())
+ result := partition.tryAllocate() // ask1 occupies node1
+ assert.Assert(t, result != nil && result.Allocation != nil, "no alloc")
+ assert.Equal(t, objects.Allocated, result.ResultType)
+ allocationKey := result.Allocation.GetAllocationKey()
+ assert.Equal(t, "alloc-1", allocationKey)
assert.Equal(t, 0, partition.getReservationCount())
- alloc = partition.tryAllocate() // ask2 gets reserved
- assert.Assert(t, alloc == nil)
+ result = partition.tryAllocate() // ask2 gets reserved
+ assert.Assert(t, result == nil)
assert.Equal(t, 1, partition.getReservationCount())
partition.removeAllocation(&si.AllocationRelease{
@@ -4082,9 +4084,10 @@ func TestReservationTracking(t *testing.T) {
ApplicationID: appID1,
TerminationType: si.TerminationType_STOPPED_BY_RM,
}) // terminate ask1
- alloc = partition.tryReservedAllocate() // allocate reservation
+ result = partition.tryReservedAllocate() // allocate reservation
+ assert.Assert(t, result != nil && result.Allocation != nil, "no alloc")
assert.Equal(t, 0, partition.getReservationCount())
- assert.Equal(t, "alloc-2", alloc.GetAllocationKey())
+ assert.Equal(t, "alloc-2", result.Allocation.GetAllocationKey())
}
//nolint:funlen
@@ -4220,13 +4223,13 @@ func TestLimitMaxApplications(t *testing.T) {
err = app1.AddAllocationAsk(newAllocationAsk(allocKey, appID1, res))
assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
- alloc := partition.tryAllocate()
- if alloc == nil {
+ result := partition.tryAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.Allocated, "result type is not the expected allocated")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
+ assert.Equal(t, result.ResultType, objects.Allocated, "result type is not the expected allocated")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated")
// add app2
app2 := newApplication(appID2, "default", defQueue)
@@ -4236,8 +4239,8 @@ func TestLimitMaxApplications(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-2 to app-1")
assert.Equal(t, app2.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
- alloc = partition.tryAllocate()
- assert.Equal(t, alloc == nil, true, "allocation should not have happened as max apps reached")
+ result = partition.tryAllocate()
+ assert.Equal(t, result == nil, true, "allocation should not have happened as max apps reached")
})
}
}
@@ -4378,13 +4381,13 @@ func TestLimitMaxApplicationsForReservedAllocation(t *testing.T) {
assert.NilError(t, err, "failed to add ask alloc-1 to app-1")
partition.reserve(app1, node, app1AllocAsk)
- alloc := partition.tryReservedAllocate()
- if alloc == nil {
+ result := partition.tryReservedAllocate()
+ if result == nil || result.Allocation == nil {
t.Fatal("allocation did not return any allocation")
}
- assert.Equal(t, alloc.GetResultType(), objects.AllocatedReserved, "result type is not the expected allocated reserved")
- assert.Equal(t, alloc.GetApplicationID(), appID1, "expected application app-1 to be allocated reserved")
- assert.Equal(t, alloc.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated reserved")
+ assert.Equal(t, result.ResultType, objects.AllocatedReserved, "result type is not the expected allocated reserved")
+ assert.Equal(t, result.Allocation.GetApplicationID(), appID1, "expected application app-1 to be allocated reserved")
+ assert.Equal(t, result.Allocation.GetAllocationKey(), allocKey, "expected ask alloc-1 to be allocated reserved")
// add app2
app2 := newApplication(appID2, "default", defQueue)
@@ -4396,8 +4399,8 @@ func TestLimitMaxApplicationsForReservedAllocation(t *testing.T) {
assert.Equal(t, app2.CurrentState(), objects.Accepted.String(), "application should have moved to accepted state")
partition.reserve(app2, node, app2AllocAsk)
- alloc = partition.tryReservedAllocate()
- assert.Equal(t, alloc == nil, true, "allocation should not have happened as max apps reached")
+ result = partition.tryReservedAllocate()
+ assert.Assert(t, result == nil, "allocation should not have happened as max apps reached")
})
}
}
@@ -4503,19 +4506,19 @@ func TestPlaceholderAllocationAndReplacementAfterRecovery(t *testing.T) {
assert.NilError(t, err, "failed to add real ask")
// get an allocation for "placeholder2"
- alloc := partition.tryAllocate()
- assert.Assert(t, alloc != nil, "no allocation occurred")
- assert.Equal(t, objects.Allocated, alloc.GetResultType())
- assert.Equal(t, "placeholder2", alloc.GetAllocationKey())
- assert.Equal(t, "tg-2", alloc.GetTaskGroup())
- assert.Equal(t, "node-1", alloc.GetNodeID())
+ result := partition.tryAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "no allocation occurred")
+ assert.Equal(t, objects.Allocated, result.ResultType)
+ assert.Equal(t, "placeholder2", result.Allocation.GetAllocationKey())
+ assert.Equal(t, "tg-2", result.Allocation.GetTaskGroup())
+ assert.Equal(t, "node-1", result.NodeID)
// real allocation gets replaced
- alloc = partition.tryPlaceholderAllocate()
- assert.Assert(t, alloc != nil, "no placeholder replacement occurred")
- assert.Equal(t, objects.Replaced, alloc.GetResultType())
- assert.Equal(t, "real-alloc", alloc.GetAllocationKey())
- assert.Equal(t, "tg-1", alloc.GetTaskGroup())
+ result = partition.tryPlaceholderAllocate()
+ assert.Assert(t, result != nil && result.Allocation != nil, "no placeholder replacement occurred")
+ assert.Equal(t, objects.Replaced, result.ResultType)
+ assert.Equal(t, "real-alloc", result.Allocation.GetAllocationKey())
+ assert.Equal(t, "tg-1", result.Allocation.GetTaskGroup())
// remove the terminated placeholder allocation
released, confirmed := partition.removeAllocation(&si.AllocationRelease{
---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@yunikorn.apache.org
For additional commands, e-mail: issues-help@yunikorn.apache.org