From 892c7ddee3214dfff7a483dc5cd2ab0171c680de Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Mon, 4 Jan 2016 14:23:06 -0800 Subject: [PATCH] Fix bug, add tests, and cli output --- api/allocations.go | 1 + command/monitor.go | 8 ++++++++ scheduler/generic_sched.go | 7 ++++--- scheduler/generic_sched_test.go | 5 +++++ scheduler/system_sched.go | 22 +++++++++++----------- scheduler/system_sched_test.go | 5 +++++ 6 files changed, 34 insertions(+), 14 deletions(-) diff --git a/api/allocations.go b/api/allocations.go index 73f600d7e8a..e2885507f9b 100644 --- a/api/allocations.go +++ b/api/allocations.go @@ -62,6 +62,7 @@ type Allocation struct { type AllocationMetric struct { NodesEvaluated int NodesFiltered int + NodesAvailable map[string]int ClassFiltered map[string]int ConstraintFiltered map[string]int NodesExhausted int diff --git a/command/monitor.go b/command/monitor.go index be9b816dc24..5fd6050b182 100644 --- a/command/monitor.go +++ b/command/monitor.go @@ -280,6 +280,14 @@ func dumpAllocStatus(ui cli.Ui, alloc *api.Allocation) { ui.Output(" * No nodes were eligible for evaluation") } + // Print a helpful message if the user has asked for a DC that has no + // available nodes. + for dc, available := range alloc.Metrics.NodesAvailable { + if available == 0 { + ui.Output(fmt.Sprintf(" * No nodes are available in datacenter %q", dc)) + } + } + // Print filter info for class, num := range alloc.Metrics.ClassFiltered { ui.Output(fmt.Sprintf(" * Class %q filtered %d nodes", class, num)) diff --git a/scheduler/generic_sched.go b/scheduler/generic_sched.go index 6e76558784c..0f1fb757ae6 100644 --- a/scheduler/generic_sched.go +++ b/scheduler/generic_sched.go @@ -250,9 +250,6 @@ func (s *GenericScheduler) computePlacements(place []allocTuple) error { return err } - // Store the available nodes by datacenter - s.ctx.Metrics().NodesAvailable = byDC - // Update the set of placement ndoes s.stack.SetNodes(nodes) @@ -282,6 +279,9 @@ func (s *GenericScheduler) computePlacements(place []allocTuple) error { Metrics: s.ctx.Metrics(), } + // Store the available nodes by datacenter + s.ctx.Metrics().NodesAvailable = byDC + // Set fields based on if we found an allocation option if option != nil { // Generate the service ids for the tasks which this allocation is going @@ -303,5 +303,6 @@ func (s *GenericScheduler) computePlacements(place []allocTuple) error { failedTG[missing.TaskGroup] = alloc } } + return nil } diff --git a/scheduler/generic_sched_test.go b/scheduler/generic_sched_test.go index 7af4c4fb2a3..402ae061ff8 100644 --- a/scheduler/generic_sched_test.go +++ b/scheduler/generic_sched_test.go @@ -123,6 +123,11 @@ func TestServiceSched_JobRegister_AllocFail(t *testing.T) { t.Fatalf("bad: %#v", out[0].Metrics) } + // Check the available nodes + if count, ok := out[0].Metrics.NodesAvailable["dc1"]; !ok || count != 0 { + t.Fatalf("bad: %#v", out[0].Metrics) + } + h.AssertEvalStatus(t, structs.EvalStatusComplete) } diff --git a/scheduler/system_sched.go b/scheduler/system_sched.go index 4909a0059e4..9b352b81fb1 100644 --- a/scheduler/system_sched.go +++ b/scheduler/system_sched.go @@ -25,12 +25,13 @@ type SystemScheduler struct { state State planner Planner - eval *structs.Evaluation - job *structs.Job - plan *structs.Plan - ctx *EvalContext - stack *SystemStack - nodes []*structs.Node + eval *structs.Evaluation + job *structs.Job + plan *structs.Plan + ctx *EvalContext + stack *SystemStack + nodes []*structs.Node + nodesByDC map[string]int limitReached bool nextEval *structs.Evaluation @@ -86,14 +87,10 @@ func (s *SystemScheduler) process() (bool, error) { // Get the ready nodes in the required datacenters if s.job != nil { - var byDC map[string]int - s.nodes, byDC, err = readyNodesInDCs(s.state, s.job.Datacenters) + s.nodes, s.nodesByDC, err = readyNodesInDCs(s.state, s.job.Datacenters) if err != nil { return false, fmt.Errorf("failed to get ready nodes: %v", err) } - - // Store the available nodes by datacenter - s.ctx.Metrics().NodesAvailable = byDC } // Create a plan @@ -250,6 +247,9 @@ func (s *SystemScheduler) computePlacements(place []allocTuple) error { Metrics: s.ctx.Metrics(), } + // Store the available nodes by datacenter + s.ctx.Metrics().NodesAvailable = s.nodesByDC + // Set fields based on if we found an allocation option if option != nil { // Generate the service ids for the tasks that this allocation is going diff --git a/scheduler/system_sched_test.go b/scheduler/system_sched_test.go index c6f186ee3f5..fae5f322a76 100644 --- a/scheduler/system_sched_test.go +++ b/scheduler/system_sched_test.go @@ -59,6 +59,11 @@ func TestSystemSched_JobRegister(t *testing.T) { t.Fatalf("bad: %#v", out) } + // Check the available nodes + if count, ok := out[0].Metrics.NodesAvailable["dc1"]; !ok || count != 10 { + t.Fatalf("bad: %#v", out[0].Metrics) + } + h.AssertEvalStatus(t, structs.EvalStatusComplete) }