// updateNonTerminalAllocsToLost updates the allocations which are in pending/running state on tainted node // to lost func updateNonTerminalAllocsToLost(plan *structs.Plan, tainted map[string]*structs.Node, allocs []*structs.Allocation) { for _, alloc := range allocs { if _, ok := tainted[alloc.NodeID]; ok && alloc.DesiredStatus == structs.AllocDesiredStatusStop && (alloc.ClientStatus == structs.AllocClientStatusRunning || alloc.ClientStatus == structs.AllocClientStatusPending) { plan.AppendUpdate(alloc, structs.AllocDesiredStatusStop, allocLost, structs.AllocClientStatusLost) } } }
// SubmitPlan is used to submit a plan for consideration. This allows // the worker to act as the planner for the scheduler. func (w *Worker) SubmitPlan(plan *structs.Plan) (*structs.PlanResult, scheduler.State, error) { // Check for a shutdown before plan submission if w.srv.IsShutdown() { return nil, nil, fmt.Errorf("shutdown while planning") } defer metrics.MeasureSince([]string{"nomad", "worker", "submit_plan"}, time.Now()) // Add the evaluation token to the plan plan.EvalToken = w.evalToken // Setup the request req := structs.PlanRequest{ Plan: plan, WriteRequest: structs.WriteRequest{ Region: w.srv.config.Region, }, } var resp structs.PlanResponse SUBMIT: // Make the RPC call if err := w.srv.RPC("Plan.Submit", &req, &resp); err != nil { w.logger.Printf("[ERR] worker: failed to submit plan for evaluation %s: %v", plan.EvalID, err) if w.shouldResubmit(err) && !w.backoffErr(backoffBaselineSlow, backoffLimitSlow) { goto SUBMIT } return nil, nil, err } else { w.logger.Printf("[DEBUG] worker: submitted plan for evaluation %s", plan.EvalID) w.backoffReset() } // Look for a result result := resp.Result if result == nil { return nil, nil, fmt.Errorf("missing result") } // Check if a state update is required. This could be required if we // planning based on stale data, which is causing issues. For example, a // node failure since the time we've started planning or conflicting task // allocations. var state scheduler.State if result.RefreshIndex != 0 { // Wait for the raft log to catchup to the evaluation w.logger.Printf("[DEBUG] worker: refreshing state to index %d for %q", result.RefreshIndex, plan.EvalID) if err := w.waitForIndex(result.RefreshIndex, raftSyncLimit); err != nil { return nil, nil, err } // Snapshot the current state snap, err := w.srv.fsm.State().Snapshot() if err != nil { return nil, nil, fmt.Errorf("failed to snapshot state: %v", err) } state = snap } // Return the result and potential state update return result, state, nil }