github.com/djenriquez/nomad-1@v0.8.1/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  	DesiredTransition  DesiredTransition
    85  	ClientStatus       string
    86  	ClientDescription  string
    87  	TaskStates         map[string]*TaskState
    88  	DeploymentID       string
    89  	DeploymentStatus   *AllocDeploymentStatus
    90  	FollowupEvalID     string
    91  	PreviousAllocation string
    92  	NextAllocation     string
    93  	RescheduleTracker  *RescheduleTracker
    94  	CreateIndex        uint64
    95  	ModifyIndex        uint64
    96  	AllocModifyIndex   uint64
    97  	CreateTime         int64
    98  	ModifyTime         int64
    99  }
   100  
   101  // AllocationMetric is used to deserialize allocation metrics.
   102  type AllocationMetric struct {
   103  	NodesEvaluated     int
   104  	NodesFiltered      int
   105  	NodesAvailable     map[string]int
   106  	ClassFiltered      map[string]int
   107  	ConstraintFiltered map[string]int
   108  	NodesExhausted     int
   109  	ClassExhausted     map[string]int
   110  	DimensionExhausted map[string]int
   111  	QuotaExhausted     []string
   112  	Scores             map[string]float64
   113  	AllocationTime     time.Duration
   114  	CoalescedFailures  int
   115  }
   116  
   117  // AllocationListStub is used to return a subset of an allocation
   118  // during list operations.
   119  type AllocationListStub struct {
   120  	ID                 string
   121  	EvalID             string
   122  	Name               string
   123  	NodeID             string
   124  	JobID              string
   125  	JobVersion         uint64
   126  	TaskGroup          string
   127  	DesiredStatus      string
   128  	DesiredDescription string
   129  	ClientStatus       string
   130  	ClientDescription  string
   131  	TaskStates         map[string]*TaskState
   132  	DeploymentStatus   *AllocDeploymentStatus
   133  	RescheduleTracker  *RescheduleTracker
   134  	FollowupEvalID     string
   135  	CreateIndex        uint64
   136  	ModifyIndex        uint64
   137  	CreateTime         int64
   138  	ModifyTime         int64
   139  }
   140  
   141  // AllocDeploymentStatus captures the status of the allocation as part of the
   142  // deployment. This can include things like if the allocation has been marked as
   143  // healthy.
   144  type AllocDeploymentStatus struct {
   145  	Healthy     *bool
   146  	ModifyIndex uint64
   147  }
   148  
   149  // AllocIndexSort reverse sorts allocs by CreateIndex.
   150  type AllocIndexSort []*AllocationListStub
   151  
   152  func (a AllocIndexSort) Len() int {
   153  	return len(a)
   154  }
   155  
   156  func (a AllocIndexSort) Less(i, j int) bool {
   157  	return a[i].CreateIndex > a[j].CreateIndex
   158  }
   159  
   160  func (a AllocIndexSort) Swap(i, j int) {
   161  	a[i], a[j] = a[j], a[i]
   162  }
   163  
   164  // RescheduleInfo is used to calculate remaining reschedule attempts
   165  // according to the given time and the task groups reschedule policy
   166  func (a Allocation) RescheduleInfo(t time.Time) (int, int) {
   167  	var reschedulePolicy *ReschedulePolicy
   168  	for _, tg := range a.Job.TaskGroups {
   169  		if *tg.Name == a.TaskGroup {
   170  			reschedulePolicy = tg.ReschedulePolicy
   171  		}
   172  	}
   173  	if reschedulePolicy == nil {
   174  		return 0, 0
   175  	}
   176  	availableAttempts := *reschedulePolicy.Attempts
   177  	interval := *reschedulePolicy.Interval
   178  	attempted := 0
   179  
   180  	// Loop over reschedule tracker to find attempts within the restart policy's interval
   181  	if a.RescheduleTracker != nil && availableAttempts > 0 && interval > 0 {
   182  		for j := len(a.RescheduleTracker.Events) - 1; j >= 0; j-- {
   183  			lastAttempt := a.RescheduleTracker.Events[j].RescheduleTime
   184  			timeDiff := t.UTC().UnixNano() - lastAttempt
   185  			if timeDiff < interval.Nanoseconds() {
   186  				attempted += 1
   187  			}
   188  		}
   189  	}
   190  	return attempted, availableAttempts
   191  }
   192  
   193  // RescheduleTracker encapsulates previous reschedule events
   194  type RescheduleTracker struct {
   195  	Events []*RescheduleEvent
   196  }
   197  
   198  // RescheduleEvent is used to keep track of previous attempts at rescheduling an allocation
   199  type RescheduleEvent struct {
   200  	// RescheduleTime is the timestamp of a reschedule attempt
   201  	RescheduleTime int64
   202  
   203  	// PrevAllocID is the ID of the previous allocation being restarted
   204  	PrevAllocID string
   205  
   206  	// PrevNodeID is the node ID of the previous allocation
   207  	PrevNodeID string
   208  }
   209  
   210  // DesiredTransition is used to mark an allocation as having a desired state
   211  // transition. This information can be used by the scheduler to make the
   212  // correct decision.
   213  type DesiredTransition struct {
   214  	// Migrate is used to indicate that this allocation should be stopped and
   215  	// migrated to another node.
   216  	Migrate *bool
   217  }
   218  
   219  // ShouldMigrate returns whether the transition object dictates a migration.
   220  func (d DesiredTransition) ShouldMigrate() bool {
   221  	return d.Migrate != nil && *d.Migrate
   222  }