Merge pull request #1067 from hashicorp/b-add-client-status-to-terminal

add client status to allocation terminal status
This commit is contained in:
Alex Dadgar 2016-04-11 13:20:39 -07:00
commit 98bbb10217
5 changed files with 59 additions and 64 deletions

View File

@ -235,12 +235,7 @@ func (c *CoreScheduler) gcEval(eval *structs.Evaluation, thresholdIndex uint64)
// Scan the allocations to ensure they are terminal and old
for _, alloc := range allocs {
// TODO: This can go away once the scheduler marks an alloc as
// DesiredStatusStop when a client fails.
allocTerminal := alloc.TerminalStatus() ||
alloc.ClientStatus == structs.AllocClientStatusComplete ||
alloc.ClientStatus == structs.AllocClientStatusFailed
if !allocTerminal || alloc.ModifyIndex > thresholdIndex {
if !alloc.TerminalStatus() || alloc.ModifyIndex > thresholdIndex {
return false, nil, nil
}
}

View File

@ -374,36 +374,26 @@ func TestCoreScheduler_NodeGC_Force(t *testing.T) {
func TestCoreScheduler_JobGC(t *testing.T) {
tests := []struct {
test, evalStatus, desiredAllocStatus, clientAllocStatus string
shouldExist bool
test, evalStatus, allocStatus string
shouldExist bool
}{
{
test: "Terminal",
evalStatus: structs.EvalStatusFailed,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusFailed,
shouldExist: false,
test: "Terminal",
evalStatus: structs.EvalStatusFailed,
allocStatus: structs.AllocDesiredStatusFailed,
shouldExist: false,
},
{
test: "Has Failed Alloc",
evalStatus: structs.EvalStatusFailed,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusFailed,
shouldExist: false,
test: "Has Alloc",
evalStatus: structs.EvalStatusFailed,
allocStatus: structs.AllocDesiredStatusRun,
shouldExist: true,
},
{
test: "Has Running Alloc",
evalStatus: structs.EvalStatusFailed,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusRun,
shouldExist: true,
},
{
test: "Has Eval",
evalStatus: structs.EvalStatusPending,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusFailed,
shouldExist: true,
test: "Has Eval",
evalStatus: structs.EvalStatusPending,
allocStatus: structs.AllocDesiredStatusFailed,
shouldExist: true,
},
}
@ -434,8 +424,7 @@ func TestCoreScheduler_JobGC(t *testing.T) {
alloc := mock.Alloc()
alloc.JobID = job.ID
alloc.EvalID = eval.ID
alloc.DesiredStatus = test.desiredAllocStatus
alloc.ClientStatus = test.clientAllocStatus
alloc.DesiredStatus = test.allocStatus
err = state.UpsertAllocs(1002, []*structs.Allocation{alloc})
if err != nil {
t.Fatalf("test(%s) err: %v", test.test, err)
@ -489,36 +478,26 @@ func TestCoreScheduler_JobGC(t *testing.T) {
func TestCoreScheduler_JobGC_Force(t *testing.T) {
tests := []struct {
test, evalStatus, desiredAllocStatus, clientAllocStatus string
shouldExist bool
test, evalStatus, allocStatus string
shouldExist bool
}{
{
test: "Terminal",
evalStatus: structs.EvalStatusFailed,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusFailed,
shouldExist: false,
test: "Terminal",
evalStatus: structs.EvalStatusFailed,
allocStatus: structs.AllocDesiredStatusFailed,
shouldExist: false,
},
{
test: "Has Failed Alloc",
evalStatus: structs.EvalStatusFailed,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusFailed,
shouldExist: false,
test: "Has Alloc",
evalStatus: structs.EvalStatusFailed,
allocStatus: structs.AllocDesiredStatusRun,
shouldExist: true,
},
{
test: "Has Running Alloc",
evalStatus: structs.EvalStatusFailed,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusRun,
shouldExist: true,
},
{
test: "Has Eval",
evalStatus: structs.EvalStatusPending,
desiredAllocStatus: structs.AllocDesiredStatusRun,
clientAllocStatus: structs.AllocDesiredStatusFailed,
shouldExist: true,
test: "Has Eval",
evalStatus: structs.EvalStatusPending,
allocStatus: structs.AllocDesiredStatusFailed,
shouldExist: true,
},
}
@ -549,8 +528,7 @@ func TestCoreScheduler_JobGC_Force(t *testing.T) {
alloc := mock.Alloc()
alloc.JobID = job.ID
alloc.EvalID = eval.ID
alloc.DesiredStatus = test.desiredAllocStatus
alloc.ClientStatus = test.clientAllocStatus
alloc.DesiredStatus = test.allocStatus
err = state.UpsertAllocs(1002, []*structs.Allocation{alloc})
if err != nil {
t.Fatalf("test(%s) err: %v", test.test, err)

View File

@ -24,17 +24,25 @@ func TestRemoveAllocs(t *testing.T) {
func TestFilterTerminalAllocs(t *testing.T) {
l := []*Allocation{
&Allocation{ID: "foo", DesiredStatus: AllocDesiredStatusRun},
&Allocation{ID: "bar", DesiredStatus: AllocDesiredStatusEvict},
&Allocation{ID: "baz", DesiredStatus: AllocDesiredStatusStop},
&Allocation{ID: "zip", DesiredStatus: AllocDesiredStatusRun},
&Allocation{
ID: "foo",
DesiredStatus: AllocDesiredStatusRun,
ClientStatus: AllocClientStatusPending,
},
&Allocation{
ID: "bam",
DesiredStatus: AllocDesiredStatusRun,
ClientStatus: AllocClientStatusComplete,
},
}
out := FilterTerminalAllocs(l)
if len(out) != 2 {
if len(out) != 1 {
t.Fatalf("bad: %#v", out)
}
if out[0].ID != "foo" && out[1].ID != "zip" {
if out[0].ID != "foo" {
t.Fatalf("bad: %#v", out)
}
}

View File

@ -2229,6 +2229,12 @@ func (a *Allocation) TerminalStatus() bool {
switch a.DesiredStatus {
case AllocDesiredStatusStop, AllocDesiredStatusEvict, AllocDesiredStatusFailed:
return true
default:
}
switch a.ClientStatus {
case AllocClientStatusComplete, AllocClientStatusFailed:
return true
default:
return false
}

View File

@ -231,8 +231,16 @@ func (s *GenericScheduler) process() (bool, error) {
// re-placed.
func (s *GenericScheduler) filterCompleteAllocs(allocs []*structs.Allocation) []*structs.Allocation {
filter := func(a *structs.Allocation) bool {
// TODO: Limit the number of times we restart a failed allocation.
return a.TerminalStatus() || a.ClientStatus == structs.AllocClientStatusFailed
// Allocs from batch jobs should be filtered when their status is failed
// so that they will be replaced. If they are complete but not failed, they
// shouldn't be replaced.
if s.batch {
return a.TerminalStatus() &&
a.ClientStatus != structs.AllocClientStatusComplete
}
// Filter terminal, non batch allocations
return a.TerminalStatus()
}
n := len(allocs)