github.com/kardianos/nomad@v0.1.3-0.20151022182107-b13df73ee850/scheduler/context.go (about) 1 package scheduler 2 3 import ( 4 "log" 5 "regexp" 6 7 "github.com/hashicorp/go-version" 8 "github.com/hashicorp/nomad/nomad/structs" 9 ) 10 11 // Context is used to track contextual information used for placement 12 type Context interface { 13 // State is used to inspect the current global state 14 State() State 15 16 // Plan returns the current plan 17 Plan() *structs.Plan 18 19 // Logger provides a way to log 20 Logger() *log.Logger 21 22 // Metrics returns the current metrics 23 Metrics() *structs.AllocMetric 24 25 // Reset is invoked after making a placement 26 Reset() 27 28 // ProposedAllocs returns the proposed allocations for a node 29 // which is the existing allocations, removing evictions, and 30 // adding any planned placements. 31 ProposedAllocs(nodeID string) ([]*structs.Allocation, error) 32 33 // RegexpCache is a cache of regular expressions 34 RegexpCache() map[string]*regexp.Regexp 35 36 // ConstraintCache is a cache of version constraints 37 ConstraintCache() map[string]version.Constraints 38 } 39 40 // EvalCache is used to cache certain things during an evaluation 41 type EvalCache struct { 42 reCache map[string]*regexp.Regexp 43 constraintCache map[string]version.Constraints 44 } 45 46 func (e *EvalCache) RegexpCache() map[string]*regexp.Regexp { 47 if e.reCache == nil { 48 e.reCache = make(map[string]*regexp.Regexp) 49 } 50 return e.reCache 51 } 52 func (e *EvalCache) ConstraintCache() map[string]version.Constraints { 53 if e.constraintCache == nil { 54 e.constraintCache = make(map[string]version.Constraints) 55 } 56 return e.constraintCache 57 } 58 59 // EvalContext is a Context used during an Evaluation 60 type EvalContext struct { 61 EvalCache 62 state State 63 plan *structs.Plan 64 logger *log.Logger 65 metrics *structs.AllocMetric 66 } 67 68 // NewEvalContext constructs a new EvalContext 69 func NewEvalContext(s State, p *structs.Plan, log *log.Logger) *EvalContext { 70 ctx := &EvalContext{ 71 state: s, 72 plan: p, 73 logger: log, 74 metrics: new(structs.AllocMetric), 75 } 76 return ctx 77 } 78 79 func (e *EvalContext) State() State { 80 return e.state 81 } 82 83 func (e *EvalContext) Plan() *structs.Plan { 84 return e.plan 85 } 86 87 func (e *EvalContext) Logger() *log.Logger { 88 return e.logger 89 } 90 91 func (e *EvalContext) Metrics() *structs.AllocMetric { 92 return e.metrics 93 } 94 95 func (e *EvalContext) SetState(s State) { 96 e.state = s 97 } 98 99 func (e *EvalContext) Reset() { 100 e.metrics = new(structs.AllocMetric) 101 } 102 103 func (e *EvalContext) ProposedAllocs(nodeID string) ([]*structs.Allocation, error) { 104 // Get the existing allocations 105 existingAlloc, err := e.state.AllocsByNode(nodeID) 106 if err != nil { 107 return nil, err 108 } 109 110 // Filter on alloc state 111 existingAlloc = structs.FilterTerminalAllocs(existingAlloc) 112 113 // Determine the proposed allocation by first removing allocations 114 // that are planned evictions and adding the new allocations. 115 proposed := existingAlloc 116 if update := e.plan.NodeUpdate[nodeID]; len(update) > 0 { 117 proposed = structs.RemoveAllocs(existingAlloc, update) 118 } 119 proposed = append(proposed, e.plan.NodeAllocation[nodeID]...) 120 121 // Ensure the return is not nil 122 if proposed == nil { 123 proposed = make([]*structs.Allocation, 0) 124 } 125 return proposed, nil 126 }