github.com/hspak/nomad@v0.7.2-0.20180309000617-bc4ae22a39a5/api/allocations.go (about)

     1  package api
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"time"
     7  )
     8  
     9  var (
    10  	// NodeDownErr marks an operation as not able to complete since the node is
    11  	// down.
    12  	NodeDownErr = fmt.Errorf("node down")
    13  )
    14  
    15  // Allocations is used to query the alloc-related endpoints.
    16  type Allocations struct {
    17  	client *Client
    18  }
    19  
    20  // Allocations returns a handle on the allocs endpoints.
    21  func (c *Client) Allocations() *Allocations {
    22  	return &Allocations{client: c}
    23  }
    24  
    25  // List returns a list of all of the allocations.
    26  func (a *Allocations) List(q *QueryOptions) ([]*AllocationListStub, *QueryMeta, error) {
    27  	var resp []*AllocationListStub
    28  	qm, err := a.client.query("/v1/allocations", &resp, q)
    29  	if err != nil {
    30  		return nil, nil, err
    31  	}
    32  	sort.Sort(AllocIndexSort(resp))
    33  	return resp, qm, nil
    34  }
    35  
    36  func (a *Allocations) PrefixList(prefix string) ([]*AllocationListStub, *QueryMeta, error) {
    37  	return a.List(&QueryOptions{Prefix: prefix})
    38  }
    39  
    40  // Info is used to retrieve a single allocation.
    41  func (a *Allocations) Info(allocID string, q *QueryOptions) (*Allocation, *QueryMeta, error) {
    42  	var resp Allocation
    43  	qm, err := a.client.query("/v1/allocation/"+allocID, &resp, q)
    44  	if err != nil {
    45  		return nil, nil, err
    46  	}
    47  	return &resp, qm, nil
    48  }
    49  
    50  func (a *Allocations) Stats(alloc *Allocation, q *QueryOptions) (*AllocResourceUsage, error) {
    51  	var resp AllocResourceUsage
    52  	path := fmt.Sprintf("/v1/client/allocation/%s/stats", alloc.ID)
    53  	_, err := a.client.query(path, &resp, q)
    54  	return &resp, err
    55  }
    56  
    57  func (a *Allocations) GC(alloc *Allocation, q *QueryOptions) error {
    58  	nodeClient, err := a.client.GetNodeClient(alloc.NodeID, q)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	var resp struct{}
    64  	_, err = nodeClient.query("/v1/client/allocation/"+alloc.ID+"/gc", &resp, nil)
    65  	return err
    66  }
    67  
    68  // Allocation is used for serialization of allocations.
    69  type Allocation struct {
    70  	ID                 string
    71  	Namespace          string
    72  	EvalID             string
    73  	Name               string
    74  	NodeID             string
    75  	JobID              string
    76  	Job                *Job
    77  	TaskGroup          string
    78  	Resources          *Resources
    79  	TaskResources      map[string]*Resources
    80  	Services           map[string]string
    81  	Metrics            *AllocationMetric
    82  	DesiredStatus      string
    83  	DesiredDescription string
    84  	ClientStatus       string
    85  	ClientDescription  string
    86  	TaskStates         map[string]*TaskState
    87  	DeploymentID       string
    88  	DeploymentStatus   *AllocDeploymentStatus
    89  	PreviousAllocation string
    90  	NextAllocation     string
    91  	RescheduleTracker  *RescheduleTracker
    92  	CreateIndex        uint64
    93  	ModifyIndex        uint64
    94  	AllocModifyIndex   uint64
    95  	CreateTime         int64
    96  	ModifyTime         int64
    97  }
    98  
    99  // AllocationMetric is used to deserialize allocation metrics.
   100  type AllocationMetric struct {
   101  	NodesEvaluated     int
   102  	NodesFiltered      int
   103  	NodesAvailable     map[string]int
   104  	ClassFiltered      map[string]int
   105  	ConstraintFiltered map[string]int
   106  	NodesExhausted     int
   107  	ClassExhausted     map[string]int
   108  	DimensionExhausted map[string]int
   109  	QuotaExhausted     []string
   110  	Scores             map[string]float64
   111  	AllocationTime     time.Duration
   112  	CoalescedFailures  int
   113  }
   114  
   115  // AllocationListStub is used to return a subset of an allocation
   116  // during list operations.
   117  type AllocationListStub struct {
   118  	ID                 string
   119  	EvalID             string
   120  	Name               string
   121  	NodeID             string
   122  	JobID              string
   123  	JobVersion         uint64
   124  	TaskGroup          string
   125  	DesiredStatus      string
   126  	DesiredDescription string
   127  	ClientStatus       string
   128  	ClientDescription  string
   129  	TaskStates         map[string]*TaskState
   130  	DeploymentStatus   *AllocDeploymentStatus
   131  	RescheduleTracker  *RescheduleTracker
   132  	CreateIndex        uint64
   133  	ModifyIndex        uint64
   134  	CreateTime         int64
   135  	ModifyTime         int64
   136  }
   137  
   138  // AllocDeploymentStatus captures the status of the allocation as part of the
   139  // deployment. This can include things like if the allocation has been marked as
   140  // healthy.
   141  type AllocDeploymentStatus struct {
   142  	Healthy     *bool
   143  	ModifyIndex uint64
   144  }
   145  
   146  // AllocIndexSort reverse sorts allocs by CreateIndex.
   147  type AllocIndexSort []*AllocationListStub
   148  
   149  func (a AllocIndexSort) Len() int {
   150  	return len(a)
   151  }
   152  
   153  func (a AllocIndexSort) Less(i, j int) bool {
   154  	return a[i].CreateIndex > a[j].CreateIndex
   155  }
   156  
   157  func (a AllocIndexSort) Swap(i, j int) {
   158  	a[i], a[j] = a[j], a[i]
   159  }
   160  
   161  // RescheduleInfo is used to calculate remaining reschedule attempts
   162  // according to the given time and the task groups reschedule policy
   163  func (a Allocation) RescheduleInfo(t time.Time) (int, int) {
   164  	var reschedulePolicy *ReschedulePolicy
   165  	for _, tg := range a.Job.TaskGroups {
   166  		if *tg.Name == a.TaskGroup {
   167  			reschedulePolicy = tg.ReschedulePolicy
   168  		}
   169  	}
   170  	if reschedulePolicy == nil {
   171  		return 0, 0
   172  	}
   173  	availableAttempts := *reschedulePolicy.Attempts
   174  	interval := *reschedulePolicy.Interval
   175  	attempted := 0
   176  
   177  	// Loop over reschedule tracker to find attempts within the restart policy's interval
   178  	if a.RescheduleTracker != nil && availableAttempts > 0 && interval > 0 {
   179  		for j := len(a.RescheduleTracker.Events) - 1; j >= 0; j-- {
   180  			lastAttempt := a.RescheduleTracker.Events[j].RescheduleTime
   181  			timeDiff := t.UTC().UnixNano() - lastAttempt
   182  			if timeDiff < interval.Nanoseconds() {
   183  				attempted += 1
   184  			}
   185  		}
   186  	}
   187  	return attempted, availableAttempts
   188  }
   189  
   190  // RescheduleTracker encapsulates previous reschedule events
   191  type RescheduleTracker struct {
   192  	Events []*RescheduleEvent
   193  }
   194  
   195  // RescheduleEvent is used to keep track of previous attempts at rescheduling an allocation
   196  type RescheduleEvent struct {
   197  	// RescheduleTime is the timestamp of a reschedule attempt
   198  	RescheduleTime int64
   199  
   200  	// PrevAllocID is the ID of the previous allocation being restarted
   201  	PrevAllocID string
   202  
   203  	// PrevNodeID is the node ID of the previous allocation
   204  	PrevNodeID string
   205  }