core: reschedule evicted batch job when resources become available
This PR fixes a bug where an evicted batch job would not be rescheduled once resources become available. Closes #9890
This commit is contained in:
parent
0399b7e4c5
commit
0692190e12
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
core: Fixed a bug where an evicted batch job would not be rescheduled
|
||||||
|
```
|
|
@ -401,7 +401,8 @@ func (a allocSet) filterByRescheduleable(isBatch, isDisconnecting bool, now time
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldFilter returns whether the alloc should be ignored or considered untainted
|
// shouldFilter returns whether the alloc should be ignored or considered untainted.
|
||||||
|
//
|
||||||
// Ignored allocs are filtered out.
|
// Ignored allocs are filtered out.
|
||||||
// Untainted allocs count against the desired total.
|
// Untainted allocs count against the desired total.
|
||||||
// Filtering logic for batch jobs:
|
// Filtering logic for batch jobs:
|
||||||
|
@ -418,11 +419,13 @@ func shouldFilter(alloc *structs.Allocation, isBatch bool) (untainted, ignore bo
|
||||||
// complete but not failed, they shouldn't be replaced.
|
// complete but not failed, they shouldn't be replaced.
|
||||||
if isBatch {
|
if isBatch {
|
||||||
switch alloc.DesiredStatus {
|
switch alloc.DesiredStatus {
|
||||||
case structs.AllocDesiredStatusStop, structs.AllocDesiredStatusEvict:
|
case structs.AllocDesiredStatusStop:
|
||||||
if alloc.RanSuccessfully() {
|
if alloc.RanSuccessfully() {
|
||||||
return true, false
|
return true, false
|
||||||
}
|
}
|
||||||
return false, true
|
return false, true
|
||||||
|
case structs.AllocDesiredStatusEvict:
|
||||||
|
return false, true
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package scheduler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/nomad/ci"
|
"github.com/hashicorp/nomad/ci"
|
||||||
|
@ -826,3 +825,110 @@ func TestAllocSet_filterByTainted(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReconcile_shouldFilter(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
batch bool
|
||||||
|
failed bool
|
||||||
|
desiredStatus string
|
||||||
|
clientStatus string
|
||||||
|
|
||||||
|
untainted bool
|
||||||
|
ignore bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "batch running",
|
||||||
|
batch: true,
|
||||||
|
failed: false,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusRun,
|
||||||
|
clientStatus: structs.AllocClientStatusRunning,
|
||||||
|
untainted: true,
|
||||||
|
ignore: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "batch stopped success",
|
||||||
|
batch: true,
|
||||||
|
failed: false,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusStop,
|
||||||
|
clientStatus: structs.AllocClientStatusRunning,
|
||||||
|
untainted: true,
|
||||||
|
ignore: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "batch stopped failed",
|
||||||
|
batch: true,
|
||||||
|
failed: true,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusStop,
|
||||||
|
clientStatus: structs.AllocClientStatusComplete,
|
||||||
|
untainted: false,
|
||||||
|
ignore: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "batch evicted",
|
||||||
|
batch: true,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusEvict,
|
||||||
|
clientStatus: structs.AllocClientStatusComplete,
|
||||||
|
untainted: false,
|
||||||
|
ignore: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "batch failed",
|
||||||
|
batch: true,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusRun,
|
||||||
|
clientStatus: structs.AllocClientStatusFailed,
|
||||||
|
untainted: false,
|
||||||
|
ignore: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "service running",
|
||||||
|
batch: false,
|
||||||
|
failed: false,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusRun,
|
||||||
|
clientStatus: structs.AllocClientStatusRunning,
|
||||||
|
untainted: false,
|
||||||
|
ignore: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "service stopped",
|
||||||
|
batch: false,
|
||||||
|
failed: false,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusStop,
|
||||||
|
clientStatus: structs.AllocClientStatusComplete,
|
||||||
|
untainted: false,
|
||||||
|
ignore: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "service evicted",
|
||||||
|
batch: false,
|
||||||
|
failed: false,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusEvict,
|
||||||
|
clientStatus: structs.AllocClientStatusComplete,
|
||||||
|
untainted: false,
|
||||||
|
ignore: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "service client complete",
|
||||||
|
batch: false,
|
||||||
|
failed: false,
|
||||||
|
desiredStatus: structs.AllocDesiredStatusRun,
|
||||||
|
clientStatus: structs.AllocClientStatusComplete,
|
||||||
|
untainted: false,
|
||||||
|
ignore: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
|
alloc := &structs.Allocation{
|
||||||
|
DesiredStatus: tc.desiredStatus,
|
||||||
|
TaskStates: map[string]*structs.TaskState{"task": {State: structs.TaskStateDead, Failed: tc.failed}},
|
||||||
|
ClientStatus: tc.clientStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
untainted, ignore := shouldFilter(alloc, tc.batch)
|
||||||
|
require.Equal(t, tc.untainted, untainted)
|
||||||
|
require.Equal(t, tc.ignore, ignore)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue