github.com/zhizhiboom/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/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  	// Deprecated, replaced with ScoreMetaData
   113  	Scores            map[string]float64
   114  	AllocationTime    time.Duration
   115  	CoalescedFailures int
   116  	ScoreMetaData     []*NodeScoreMeta
   117  }
   118  
   119  // NodeScoreMeta is used to serialize node scoring metadata
   120  // displayed in the CLI during verbose mode
   121  type NodeScoreMeta struct {
   122  	NodeID    string
   123  	Scores    map[string]float64
   124  	NormScore float64
   125  }
   126  
   127  // AllocationListStub is used to return a subset of an allocation
   128  // during list operations.
   129  type AllocationListStub struct {
   130  	ID                 string
   131  	EvalID             string
   132  	Name               string
   133  	NodeID             string
   134  	JobID              string
   135  	JobVersion         uint64
   136  	TaskGroup          string
   137  	DesiredStatus      string
   138  	DesiredDescription string
   139  	ClientStatus       string
   140  	ClientDescription  string
   141  	TaskStates         map[string]*TaskState
   142  	DeploymentStatus   *AllocDeploymentStatus
   143  	FollowupEvalID     string
   144  	RescheduleTracker  *RescheduleTracker
   145  	CreateIndex        uint64
   146  	ModifyIndex        uint64
   147  	CreateTime         int64
   148  	ModifyTime         int64
   149  }
   150  
   151  // AllocDeploymentStatus captures the status of the allocation as part of the
   152  // deployment. This can include things like if the allocation has been marked as
   153  // healthy.
   154  type AllocDeploymentStatus struct {
   155  	Healthy     *bool
   156  	Timestamp   time.Time
   157  	Canary      bool
   158  	ModifyIndex uint64
   159  }
   160  
   161  // AllocIndexSort reverse sorts allocs by CreateIndex.
   162  type AllocIndexSort []*AllocationListStub
   163  
   164  func (a AllocIndexSort) Len() int {
   165  	return len(a)
   166  }
   167  
   168  func (a AllocIndexSort) Less(i, j int) bool {
   169  	return a[i].CreateIndex > a[j].CreateIndex
   170  }
   171  
   172  func (a AllocIndexSort) Swap(i, j int) {
   173  	a[i], a[j] = a[j], a[i]
   174  }
   175  
   176  // RescheduleInfo is used to calculate remaining reschedule attempts
   177  // according to the given time and the task groups reschedule policy
   178  func (a Allocation) RescheduleInfo(t time.Time) (int, int) {
   179  	var reschedulePolicy *ReschedulePolicy
   180  	for _, tg := range a.Job.TaskGroups {
   181  		if *tg.Name == a.TaskGroup {
   182  			reschedulePolicy = tg.ReschedulePolicy
   183  		}
   184  	}
   185  	if reschedulePolicy == nil {
   186  		return 0, 0
   187  	}
   188  	availableAttempts := *reschedulePolicy.Attempts
   189  	interval := *reschedulePolicy.Interval
   190  	attempted := 0
   191  
   192  	// Loop over reschedule tracker to find attempts within the restart policy's interval
   193  	if a.RescheduleTracker != nil && availableAttempts > 0 && interval > 0 {
   194  		for j := len(a.RescheduleTracker.Events) - 1; j >= 0; j-- {
   195  			lastAttempt := a.RescheduleTracker.Events[j].RescheduleTime
   196  			timeDiff := t.UTC().UnixNano() - lastAttempt
   197  			if timeDiff < interval.Nanoseconds() {
   198  				attempted += 1
   199  			}
   200  		}
   201  	}
   202  	return attempted, availableAttempts
   203  }
   204  
   205  // RescheduleTracker encapsulates previous reschedule events
   206  type RescheduleTracker struct {
   207  	Events []*RescheduleEvent
   208  }
   209  
   210  // RescheduleEvent is used to keep track of previous attempts at rescheduling an allocation
   211  type RescheduleEvent struct {
   212  	// RescheduleTime is the timestamp of a reschedule attempt
   213  	RescheduleTime int64
   214  
   215  	// PrevAllocID is the ID of the previous allocation being restarted
   216  	PrevAllocID string
   217  
   218  	// PrevNodeID is the node ID of the previous allocation
   219  	PrevNodeID string
   220  }
   221  
   222  // DesiredTransition is used to mark an allocation as having a desired state
   223  // transition. This information can be used by the scheduler to make the
   224  // correct decision.
   225  type DesiredTransition struct {
   226  	// Migrate is used to indicate that this allocation should be stopped and
   227  	// migrated to another node.
   228  	Migrate *bool
   229  
   230  	// Reschedule is used to indicate that this allocation is eligible to be
   231  	// rescheduled.
   232  	Reschedule *bool
   233  }
   234  
   235  // ShouldMigrate returns whether the transition object dictates a migration.
   236  func (d DesiredTransition) ShouldMigrate() bool {
   237  	return d.Migrate != nil && *d.Migrate
   238  }