mirror of
https://github.com/kemko/nomad.git
synced 2026-01-04 17:35:43 +03:00
scheduler: implementing driver iterator
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
@@ -59,6 +60,53 @@ func NewRandomIterator(ctx Context, nodes []*structs.Node) *StaticIterator {
|
||||
return NewStaticIterator(ctx, nodes)
|
||||
}
|
||||
|
||||
// DriverIterator is a FeasibleIterator which returns nodes that
|
||||
// have the drivers necessary to scheduler a task group.
|
||||
type DriverIterator struct {
|
||||
ctx Context
|
||||
source FeasibleIterator
|
||||
drivers map[string]struct{}
|
||||
}
|
||||
|
||||
// NewDriverIterator creates a DriverIterator from a source and set of drivers
|
||||
func NewDriverIterator(ctx Context, source FeasibleIterator, drivers map[string]struct{}) *DriverIterator {
|
||||
iter := &DriverIterator{
|
||||
ctx: ctx,
|
||||
source: source,
|
||||
drivers: drivers,
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func (iter *DriverIterator) Next() *structs.Node {
|
||||
for {
|
||||
// Get the next option from the source
|
||||
option := iter.source.Next()
|
||||
if option == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use this node if possible
|
||||
if iter.hasDrivers(option) {
|
||||
return option
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hasDrivers is used to check if the node has all the appropriate
|
||||
// drivers for this task group. Drivers are registered as node attribute
|
||||
// like "driver.docker=1" with their corresponding version.
|
||||
func (iter *DriverIterator) hasDrivers(option *structs.Node) bool {
|
||||
for driver := range iter.drivers {
|
||||
driverStr := fmt.Sprintf("driver.%s", driver)
|
||||
_, ok := option.Attributes[driverStr]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ConstraintIterator is a FeasibleIterator which returns nodes
|
||||
// that match a given set of constraints. This is used to filter
|
||||
// on job, task group, and task constraints.
|
||||
@@ -97,40 +145,3 @@ func (iter *ConstraintIterator) meetsConstraints(option *structs.Node) bool {
|
||||
// TODO:
|
||||
return true
|
||||
}
|
||||
|
||||
// DriverIterator is a FeasibleIterator which returns nodes that
|
||||
// have the drivers necessary to scheduler a task group.
|
||||
type DriverIterator struct {
|
||||
ctx Context
|
||||
source FeasibleIterator
|
||||
drivers map[string]struct{}
|
||||
}
|
||||
|
||||
// NewDriverIterator creates a DriverIterator from a source and set of drivers
|
||||
func NewDriverIterator(ctx Context, source FeasibleIterator, drivers map[string]struct{}) *DriverIterator {
|
||||
iter := &DriverIterator{
|
||||
ctx: ctx,
|
||||
source: source,
|
||||
drivers: drivers,
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func (iter *DriverIterator) Next() *structs.Node {
|
||||
for {
|
||||
// Get the next option from the source
|
||||
option := iter.source.Next()
|
||||
if option == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use this node if possible
|
||||
if iter.hasDrivers(option) {
|
||||
return option
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (iter *DriverIterator) hasDrivers(option *structs.Node) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -35,3 +35,38 @@ func TestRandomIterator(t *testing.T) {
|
||||
t.Fatalf("same order")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDriverIterator(t *testing.T) {
|
||||
ctx := NewEvalContext()
|
||||
nodes := []*structs.Node{
|
||||
mock.Node(),
|
||||
mock.Node(),
|
||||
mock.Node(),
|
||||
}
|
||||
static := NewStaticIterator(ctx, nodes)
|
||||
|
||||
nodes[0].Attributes["driver.foo"] = "2"
|
||||
nodes[2].Attributes["driver.foo"] = "2"
|
||||
|
||||
drivers := map[string]struct{}{
|
||||
"docker": struct{}{},
|
||||
"foo": struct{}{},
|
||||
}
|
||||
driver := NewDriverIterator(ctx, static, drivers)
|
||||
|
||||
var out []*structs.Node
|
||||
for {
|
||||
next := driver.Next()
|
||||
if next == nil {
|
||||
break
|
||||
}
|
||||
out = append(out, next)
|
||||
}
|
||||
|
||||
if len(out) != 2 {
|
||||
t.Fatalf("missing nodes")
|
||||
}
|
||||
if out[0] != nodes[0] || out[1] != nodes[2] {
|
||||
t.Fatalf("bad: %#v", out)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user