scheduler: testing bin pack scoring
This commit is contained in:
parent
022e583a2a
commit
f5e37c926c
|
@ -14,7 +14,10 @@ func testContext(t *testing.T) (*state.StateStore, *EvalContext) {
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
plan := new(structs.Plan)
|
||||
plan := &structs.Plan{
|
||||
NodeEvict: make(map[string][]string),
|
||||
NodeAllocation: make(map[string][]*structs.Allocation),
|
||||
}
|
||||
|
||||
logger := log.New(os.Stderr, "", log.LstdFlags)
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package scheduler
|
||||
|
||||
import "github.com/hashicorp/nomad/nomad/structs"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
// Rank is used to provide a score and various ranking metadata
|
||||
// along with a node when iterating. This state can be modified as
|
||||
|
@ -10,6 +14,10 @@ type RankedNode struct {
|
|||
Score float64
|
||||
}
|
||||
|
||||
func (r *RankedNode) GoString() string {
|
||||
return fmt.Sprintf("<Node: %s Score: %0.3f>", r.Node.ID, r.Score)
|
||||
}
|
||||
|
||||
// RankFeasibleIterator is used to iteratively yield nodes along
|
||||
// with ranking metadata. The iterators may manage some state for
|
||||
// performance optimizations.
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestFeasibleRankIterator(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBinPackIterator_Simple_NoExistingAlloc(t *testing.T) {
|
||||
func TestBinPackIterator_NoExistingAlloc(t *testing.T) {
|
||||
_, ctx := testContext(t)
|
||||
nodes := []*RankedNode{
|
||||
&RankedNode{
|
||||
|
@ -90,6 +90,209 @@ func TestBinPackIterator_Simple_NoExistingAlloc(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBinPackIterator_PlannedAlloc(t *testing.T) {
|
||||
_, ctx := testContext(t)
|
||||
nodes := []*RankedNode{
|
||||
&RankedNode{
|
||||
Node: &structs.Node{
|
||||
// Perfect fit
|
||||
ID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
&RankedNode{
|
||||
Node: &structs.Node{
|
||||
// Perfect fit
|
||||
ID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
static := NewStaticRankIterator(ctx, nodes)
|
||||
|
||||
// Add a planned alloc to node1 that fills it
|
||||
plan := ctx.Plan()
|
||||
plan.NodeAllocation[nodes[0].Node.ID] = []*structs.Allocation{
|
||||
&structs.Allocation{
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Add a planned alloc to node2 that half fills it
|
||||
plan.NodeAllocation[nodes[1].Node.ID] = []*structs.Allocation{
|
||||
&structs.Allocation{
|
||||
Resources: &structs.Resources{
|
||||
CPU: 1024,
|
||||
MemoryMB: 1024,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resources := &structs.Resources{
|
||||
CPU: 1024,
|
||||
MemoryMB: 1024,
|
||||
}
|
||||
binp := NewBinPackIterator(ctx, static, resources, false, 0)
|
||||
|
||||
out := collectRanked(binp)
|
||||
if len(out) != 1 {
|
||||
t.Fatalf("Bad: %#v", out)
|
||||
}
|
||||
if out[0] != nodes[1] {
|
||||
t.Fatalf("Bad: %v", out)
|
||||
}
|
||||
|
||||
if out[0].Score != 18 {
|
||||
t.Fatalf("Bad: %v", out[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinPackIterator_ExistingAlloc(t *testing.T) {
|
||||
state, ctx := testContext(t)
|
||||
nodes := []*RankedNode{
|
||||
&RankedNode{
|
||||
Node: &structs.Node{
|
||||
// Perfect fit
|
||||
ID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
&RankedNode{
|
||||
Node: &structs.Node{
|
||||
// Perfect fit
|
||||
ID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
static := NewStaticRankIterator(ctx, nodes)
|
||||
|
||||
// Add existing allocations
|
||||
alloc1 := &structs.Allocation{
|
||||
ID: mock.GenerateUUID(),
|
||||
NodeID: nodes[0].Node.ID,
|
||||
JobID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
}
|
||||
alloc2 := &structs.Allocation{
|
||||
ID: mock.GenerateUUID(),
|
||||
NodeID: nodes[1].Node.ID,
|
||||
JobID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 1024,
|
||||
MemoryMB: 1024,
|
||||
},
|
||||
}
|
||||
noErr(t, state.UpdateAllocations(1000, nil, []*structs.Allocation{alloc1, alloc2}))
|
||||
|
||||
resources := &structs.Resources{
|
||||
CPU: 1024,
|
||||
MemoryMB: 1024,
|
||||
}
|
||||
binp := NewBinPackIterator(ctx, static, resources, false, 0)
|
||||
|
||||
out := collectRanked(binp)
|
||||
if len(out) != 1 {
|
||||
t.Fatalf("Bad: %#v", out)
|
||||
}
|
||||
if out[0] != nodes[1] {
|
||||
t.Fatalf("Bad: %v", out)
|
||||
}
|
||||
if out[0].Score != 18 {
|
||||
t.Fatalf("Bad: %v", out[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinPackIterator_ExistingAlloc_PlannedEvict(t *testing.T) {
|
||||
state, ctx := testContext(t)
|
||||
nodes := []*RankedNode{
|
||||
&RankedNode{
|
||||
Node: &structs.Node{
|
||||
// Perfect fit
|
||||
ID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
&RankedNode{
|
||||
Node: &structs.Node{
|
||||
// Perfect fit
|
||||
ID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
static := NewStaticRankIterator(ctx, nodes)
|
||||
|
||||
// Add existing allocations
|
||||
alloc1 := &structs.Allocation{
|
||||
ID: mock.GenerateUUID(),
|
||||
NodeID: nodes[0].Node.ID,
|
||||
JobID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 2048,
|
||||
MemoryMB: 2048,
|
||||
},
|
||||
}
|
||||
alloc2 := &structs.Allocation{
|
||||
ID: mock.GenerateUUID(),
|
||||
NodeID: nodes[1].Node.ID,
|
||||
JobID: mock.GenerateUUID(),
|
||||
Resources: &structs.Resources{
|
||||
CPU: 1024,
|
||||
MemoryMB: 1024,
|
||||
},
|
||||
}
|
||||
noErr(t, state.UpdateAllocations(1000, nil, []*structs.Allocation{alloc1, alloc2}))
|
||||
|
||||
// Add a planned eviction to alloc1
|
||||
plan := ctx.Plan()
|
||||
plan.NodeEvict[nodes[0].Node.ID] = []string{alloc1.ID}
|
||||
|
||||
resources := &structs.Resources{
|
||||
CPU: 1024,
|
||||
MemoryMB: 1024,
|
||||
}
|
||||
binp := NewBinPackIterator(ctx, static, resources, false, 0)
|
||||
|
||||
out := collectRanked(binp)
|
||||
if len(out) != 2 {
|
||||
t.Fatalf("Bad: %#v", out)
|
||||
}
|
||||
if out[0] != nodes[0] || out[1] != nodes[1] {
|
||||
t.Fatalf("Bad: %v", out)
|
||||
}
|
||||
if out[0].Score < 10 || out[0].Score > 16 {
|
||||
t.Fatalf("Bad: %v", out[0])
|
||||
}
|
||||
if out[1].Score != 18 {
|
||||
t.Fatalf("Bad: %v", out[0])
|
||||
}
|
||||
}
|
||||
|
||||
func collectRanked(iter RankIterator) (out []*RankedNode) {
|
||||
for {
|
||||
next := iter.Next()
|
||||
|
|
Loading…
Reference in New Issue