scheduler: create allocs for failed placements
This commit is contained in:
parent
cabefa46bf
commit
9fd8049e16
|
@ -870,9 +870,13 @@ func (p *Plan) AppendAlloc(alloc *Allocation) {
|
|||
p.NodeAllocation[node] = append(existing, alloc)
|
||||
}
|
||||
|
||||
func (p *Plan) AppendFailed(alloc *Allocation) {
|
||||
p.FailedAllocs = append(p.FailedAllocs, alloc)
|
||||
}
|
||||
|
||||
// IsNoOp checks if this plan would do nothing
|
||||
func (p *Plan) IsNoOp() bool {
|
||||
return len(p.NodeEvict) == 0 && len(p.NodeAllocation) == 0
|
||||
return len(p.NodeEvict) == 0 && len(p.NodeAllocation) == 0 && len(p.FailedAllocs) == 0
|
||||
}
|
||||
|
||||
// PlanResult is the result of a plan submitted to the leader.
|
||||
|
|
|
@ -196,25 +196,33 @@ func (s *GenericScheduler) computePlacements(job *structs.Job, place []allocTupl
|
|||
|
||||
for _, missing := range place {
|
||||
option, size := stack.Select(missing.TaskGroup)
|
||||
var nodeID, status, desc string
|
||||
if option == nil {
|
||||
s.logger.Printf("[DEBUG] sched: %#v: failed to place alloc %s: %#v",
|
||||
s.eval, missing.Name, ctx.Metrics())
|
||||
continue
|
||||
status = structs.AllocStatusFailed
|
||||
desc = "failed to find a node for placement"
|
||||
} else {
|
||||
nodeID = option.Node.ID
|
||||
status = structs.AllocStatusPending
|
||||
}
|
||||
|
||||
// Create an allocation for this
|
||||
alloc := &structs.Allocation{
|
||||
ID: mock.GenerateUUID(),
|
||||
EvalID: s.eval.ID,
|
||||
Name: missing.Name,
|
||||
NodeID: option.Node.ID,
|
||||
JobID: job.ID,
|
||||
Job: job,
|
||||
Resources: size,
|
||||
Metrics: ctx.Metrics(),
|
||||
Status: structs.AllocStatusPending,
|
||||
ID: mock.GenerateUUID(),
|
||||
EvalID: s.eval.ID,
|
||||
Name: missing.Name,
|
||||
NodeID: nodeID,
|
||||
JobID: job.ID,
|
||||
Job: job,
|
||||
Resources: size,
|
||||
Metrics: ctx.Metrics(),
|
||||
Status: status,
|
||||
StatusDescription: desc,
|
||||
}
|
||||
if nodeID != "" {
|
||||
s.plan.AppendAlloc(alloc)
|
||||
} else {
|
||||
s.plan.AppendFailed(alloc)
|
||||
}
|
||||
s.plan.AppendAlloc(alloc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -59,6 +59,49 @@ func TestServiceSched_JobRegister(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestServiceSched_JobRegister_AllocFail(t *testing.T) {
|
||||
h := NewHarness(t)
|
||||
|
||||
// Create NO nodes
|
||||
// Create a job
|
||||
job := mock.Job()
|
||||
noErr(t, h.State.RegisterJob(h.NextIndex(), job))
|
||||
|
||||
// Create a mock evaluation to deregister the job
|
||||
eval := &structs.Evaluation{
|
||||
ID: mock.GenerateUUID(),
|
||||
Priority: job.Priority,
|
||||
TriggeredBy: structs.EvalTriggerJobRegister,
|
||||
JobID: job.ID,
|
||||
}
|
||||
|
||||
// Process the evaluation
|
||||
err := h.Process(NewServiceScheduler, eval)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Ensure a single plan
|
||||
if len(h.Plans) != 1 {
|
||||
t.Fatalf("bad: %#v", h.Plans)
|
||||
}
|
||||
plan := h.Plans[0]
|
||||
|
||||
// Ensure the plan failed to alloc
|
||||
if len(plan.FailedAllocs) != 10 {
|
||||
t.Fatalf("bad: %#v", plan)
|
||||
}
|
||||
|
||||
// Lookup the allocations by JobID
|
||||
out, err := h.State.AllocsByJob(job.ID)
|
||||
noErr(t, err)
|
||||
|
||||
// Ensure all allocations placed
|
||||
if len(out) != 10 {
|
||||
t.Fatalf("bad: %#v", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceSched_JobModify(t *testing.T) {
|
||||
h := NewHarness(t)
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ func (h *Harness) SubmitPlan(plan *structs.Plan) (*structs.PlanResult, State, er
|
|||
for _, allocList := range plan.NodeAllocation {
|
||||
allocs = append(allocs, allocList...)
|
||||
}
|
||||
allocs = append(allocs, plan.FailedAllocs...)
|
||||
|
||||
// Apply the full plan
|
||||
err := h.State.UpdateAllocations(index, evicts, allocs)
|
||||
|
|
Loading…
Reference in a new issue