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 {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
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)
|
logger := log.New(os.Stderr, "", log.LstdFlags)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package scheduler
|
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
|
// Rank is used to provide a score and various ranking metadata
|
||||||
// along with a node when iterating. This state can be modified as
|
// along with a node when iterating. This state can be modified as
|
||||||
|
@ -10,6 +14,10 @@ type RankedNode struct {
|
||||||
Score float64
|
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
|
// RankFeasibleIterator is used to iteratively yield nodes along
|
||||||
// with ranking metadata. The iterators may manage some state for
|
// with ranking metadata. The iterators may manage some state for
|
||||||
// performance optimizations.
|
// 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)
|
_, ctx := testContext(t)
|
||||||
nodes := []*RankedNode{
|
nodes := []*RankedNode{
|
||||||
&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) {
|
func collectRanked(iter RankIterator) (out []*RankedNode) {
|
||||||
for {
|
for {
|
||||||
next := iter.Next()
|
next := iter.Next()
|
||||||
|
|
Loading…
Reference in a new issue