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

wilfreds 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 5ddcbbbd [YUNIKORN-2527] Reset state of configured queue on re-add 
(#831)
5ddcbbbd is described below

commit 5ddcbbbddd38019f47e22456b1c6a797edd7fe73
Author: Wilfred Spiegelenburg <[email protected]>
AuthorDate: Wed Apr 3 22:39:49 2024 +1100

    [YUNIKORN-2527] Reset state of configured queue on re-add (#831)
    
    When a queue is removed and re-added the configured queue status is not
    reset. If that happens within the cleanup cycle, the cleanup still gets
    triggered. The queue is removed causing an inconsistency between the
    config and the queues available in the core.
    
    The object state needs to allow for moving from Draining back to Active.
    Updated tests to cover the new state transition.
    
    Closes: #831
    
    Signed-off-by: Wilfred Spiegelenburg <[email protected]>
---
 pkg/scheduler/objects/object_state.go      |  2 +-
 pkg/scheduler/objects/object_state_test.go | 10 ++---
 pkg/scheduler/objects/queue.go             |  8 ++++
 pkg/scheduler/objects/queue_test.go        | 33 +++++++++++++++-
 pkg/scheduler/partition_test.go            | 61 ++++++++++++++++++++++++++++++
 5 files changed, 106 insertions(+), 8 deletions(-)

diff --git a/pkg/scheduler/objects/object_state.go 
b/pkg/scheduler/objects/object_state.go
index 7c8a678b..3afbe595 100644
--- a/pkg/scheduler/objects/object_state.go
+++ b/pkg/scheduler/objects/object_state.go
@@ -68,7 +68,7 @@ func NewObjectState() *fsm.FSM {
                                Dst:  Draining.String(),
                        }, {
                                Name: Start.String(),
-                               Src:  []string{Active.String(), 
Stopped.String()},
+                               Src:  []string{Active.String(), 
Stopped.String(), Draining.String()},
                                Dst:  Active.String(),
                        }, {
                                Name: Stop.String(),
diff --git a/pkg/scheduler/objects/object_state_test.go 
b/pkg/scheduler/objects/object_state_test.go
index 20cab62d..dbe0180c 100644
--- a/pkg/scheduler/objects/object_state_test.go
+++ b/pkg/scheduler/objects/object_state_test.go
@@ -50,15 +50,15 @@ func TestStateTransition(t *testing.T) {
        assert.Assert(t, err == nil)
        assert.Equal(t, stateMachine.Current(), Draining.String())
 
-       // start on draining not allowed
-       err = stateMachine.Event(context.Background(), Start.String(), 
"test_object")
-       assert.Assert(t, err != nil)
-       assert.Equal(t, stateMachine.Current(), Draining.String())
-
        // stop on draining not allowed
        err = stateMachine.Event(context.Background(), Stop.String(), 
"test_object")
        assert.Assert(t, err != nil)
        assert.Equal(t, stateMachine.Current(), Draining.String())
+
+       // draining to active
+       err = stateMachine.Event(context.Background(), Start.String(), 
"test_object")
+       assert.Assert(t, err == nil)
+       assert.Equal(t, stateMachine.Current(), Active.String())
 }
 
 func TestTransitionToSelf(t *testing.T) {
diff --git a/pkg/scheduler/objects/queue.go b/pkg/scheduler/objects/queue.go
index 59a3d371..9f272284 100644
--- a/pkg/scheduler/objects/queue.go
+++ b/pkg/scheduler/objects/queue.go
@@ -328,6 +328,14 @@ func (sq *Queue) applyConf(conf configs.QueueConfig) error 
{
                sq.isManaged = true
        }
 
+       // if the queue is marked for removal reverse that state
+       if !sq.IsRunning() {
+               err = sq.handleQueueEvent(Start)
+               if err != nil {
+                       log.Log(log.SchedQueue).Info("managed queue state 
change failed",
+                               zap.String("queue", sq.QueuePath))
+               }
+       }
        prevLeaf := sq.isLeaf
        sq.isLeaf = !conf.Parent
        // Make sure the parent flag is set correctly: config might expect auto 
parent type creation
diff --git a/pkg/scheduler/objects/queue_test.go 
b/pkg/scheduler/objects/queue_test.go
index ff48eadd..f9111d65 100644
--- a/pkg/scheduler/objects/queue_test.go
+++ b/pkg/scheduler/objects/queue_test.go
@@ -632,8 +632,8 @@ func TestQueueStates(t *testing.T) {
                t.Errorf("leaf queue is not marked draining: %v", err)
        }
        err = leaf.handleQueueEvent(Start)
-       if err == nil || !leaf.IsDraining() {
-               t.Errorf("leaf queue changed state which should not happen: 
%v", err)
+       if err != nil || !leaf.IsRunning() {
+               t.Errorf("leaf queue is not marked running: %v", err)
        }
 }
 
@@ -2210,6 +2210,35 @@ func TestNewConfiguredQueue(t *testing.T) {
        assert.Assert(t, childNonLeaf.maxResource == nil)
 }
 
+func TestResetRunningState(t *testing.T) {
+       emptyConf := configs.QueueConfig{
+               Name: "not_used",
+       }
+       // create the root
+       root, err := createRootQueue(nil)
+       assert.NilError(t, err, "queue create failed")
+       // single parent under root
+       var parent *Queue
+       parent, err = createManagedQueue(root, "parent", true, nil)
+       assert.NilError(t, err, "failed to create parent queue")
+       var leaf *Queue
+       leaf, err = createManagedQueue(parent, "leaf", false, nil)
+       assert.NilError(t, err, "failed to create leaf queue")
+       if len(parent.children) == 0 {
+               t.Error("leaf queue is not added to the parent queue")
+       }
+       parent.MarkQueueForRemoval()
+       assert.Assert(t, parent.IsDraining(), "parent should be marked as 
draining")
+       assert.Assert(t, leaf.IsDraining(), "leaf should be marked as draining")
+       err = parent.applyConf(emptyConf)
+       assert.NilError(t, err, "failed to update parent")
+       assert.Assert(t, parent.IsRunning(), "parent should be running again")
+       assert.Assert(t, leaf.IsDraining(), "leaf should still be marked as 
draining")
+       err = leaf.applyConf(emptyConf)
+       assert.NilError(t, err, "failed to update leaf")
+       assert.Assert(t, leaf.IsRunning(), "leaf should be running again")
+}
+
 func TestNewRecoveryQueue(t *testing.T) {
        var err error
        if _, err = NewRecoveryQueue(nil); err == nil {
diff --git a/pkg/scheduler/partition_test.go b/pkg/scheduler/partition_test.go
index 90159e79..c42d784e 100644
--- a/pkg/scheduler/partition_test.go
+++ b/pkg/scheduler/partition_test.go
@@ -1426,6 +1426,67 @@ func TestUpdateQueues(t *testing.T) {
        assertUpdateQueues(t, "both", map[string]string{})
 }
 
+func TestReAddQueues(t *testing.T) {
+       conf := []configs.QueueConfig{
+               {
+                       Name:   "parent",
+                       Parent: true,
+                       Queues: []configs.QueueConfig{
+                               {
+                                       Name:   "leaf",
+                                       Parent: false,
+                                       Queues: nil,
+                               },
+                       },
+               },
+       }
+
+       confDefault := []configs.QueueConfig{
+               {
+                       Name:   "default",
+                       Parent: false,
+                       Queues: nil,
+               },
+               {
+                       Name:   "parent",
+                       Parent: true,
+                       Queues: nil,
+               },
+       }
+
+       partition, err := newBasePartition()
+       assert.NilError(t, err, "partition create failed")
+       // There is a queue setup as the config must be valid when we run
+       root := partition.GetQueue("root")
+       if root == nil {
+               t.Error("root queue not found in partition")
+       }
+       def := partition.GetQueue(defQueue)
+       if def == nil {
+               t.Fatal("default queue should exist")
+       }
+       err = partition.updateQueues(conf, root)
+       assert.NilError(t, err, "queue update from config failed")
+       leaf := partition.GetQueue("root.parent.leaf")
+       if leaf == nil {
+               t.Fatal("leaf queue should be created")
+       }
+       assert.Assert(t, def.IsDraining(), "'root.default' queue should have 
been marked for removal")
+       err = partition.updateQueues(confDefault, root)
+       assert.NilError(t, err, "queue update from config default failed")
+       assert.Assert(t, def.IsRunning(), "'root.default' queue should have 
been marked running again")
+       assert.Assert(t, leaf.IsDraining(), "'root.parent.leaf' queue should 
have been marked for removal")
+       partition.partitionManager.cleanQueues(root)
+       leaf = partition.GetQueue("root.parent.leaf")
+       if leaf != nil {
+               t.Fatal("leaf queue should have been cleaned up")
+       }
+       def = partition.GetQueue(defQueue)
+       if def == nil {
+               t.Fatal("default queue should still exist")
+       }
+}
+
 func TestGetApplication(t *testing.T) {
        partition, err := newBasePartition()
        assert.NilError(t, err, "partition create failed")


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

Reply via email to