github.com/diptanu/nomad@v0.5.7-0.20170516172507-d72e86cbe3d9/nomad/alloc_endpoint.go (about) 1 package nomad 2 3 import ( 4 "time" 5 6 "github.com/armon/go-metrics" 7 "github.com/hashicorp/go-memdb" 8 "github.com/hashicorp/nomad/nomad/state" 9 "github.com/hashicorp/nomad/nomad/structs" 10 ) 11 12 // Alloc endpoint is used for manipulating allocations 13 type Alloc struct { 14 srv *Server 15 } 16 17 // List is used to list the allocations in the system 18 func (a *Alloc) List(args *structs.AllocListRequest, reply *structs.AllocListResponse) error { 19 if done, err := a.srv.forward("Alloc.List", args, args, reply); done { 20 return err 21 } 22 defer metrics.MeasureSince([]string{"nomad", "alloc", "list"}, time.Now()) 23 24 // Setup the blocking query 25 opts := blockingOptions{ 26 queryOpts: &args.QueryOptions, 27 queryMeta: &reply.QueryMeta, 28 run: func(ws memdb.WatchSet, state *state.StateStore) error { 29 // Capture all the allocations 30 var err error 31 var iter memdb.ResultIterator 32 if prefix := args.QueryOptions.Prefix; prefix != "" { 33 iter, err = state.AllocsByIDPrefix(ws, prefix) 34 } else { 35 iter, err = state.Allocs(ws) 36 } 37 if err != nil { 38 return err 39 } 40 41 var allocs []*structs.AllocListStub 42 for { 43 raw := iter.Next() 44 if raw == nil { 45 break 46 } 47 alloc := raw.(*structs.Allocation) 48 allocs = append(allocs, alloc.Stub()) 49 } 50 reply.Allocations = allocs 51 52 // Use the last index that affected the jobs table 53 index, err := state.Index("allocs") 54 if err != nil { 55 return err 56 } 57 reply.Index = index 58 59 // Set the query response 60 a.srv.setQueryMeta(&reply.QueryMeta) 61 return nil 62 }} 63 return a.srv.blockingRPC(&opts) 64 } 65 66 // GetAlloc is used to lookup a particular allocation 67 func (a *Alloc) GetAlloc(args *structs.AllocSpecificRequest, 68 reply *structs.SingleAllocResponse) error { 69 if done, err := a.srv.forward("Alloc.GetAlloc", args, args, reply); done { 70 return err 71 } 72 defer metrics.MeasureSince([]string{"nomad", "alloc", "get_alloc"}, time.Now()) 73 74 // Setup the blocking query 75 opts := blockingOptions{ 76 queryOpts: &args.QueryOptions, 77 queryMeta: &reply.QueryMeta, 78 run: func(ws memdb.WatchSet, state *state.StateStore) error { 79 // Lookup the allocation 80 out, err := state.AllocByID(ws, args.AllocID) 81 if err != nil { 82 return err 83 } 84 85 // Setup the output 86 reply.Alloc = out 87 if out != nil { 88 reply.Index = out.ModifyIndex 89 } else { 90 // Use the last index that affected the allocs table 91 index, err := state.Index("allocs") 92 if err != nil { 93 return err 94 } 95 reply.Index = index 96 } 97 98 // Set the query response 99 a.srv.setQueryMeta(&reply.QueryMeta) 100 return nil 101 }} 102 return a.srv.blockingRPC(&opts) 103 } 104 105 // GetAllocs is used to lookup a set of allocations 106 func (a *Alloc) GetAllocs(args *structs.AllocsGetRequest, 107 reply *structs.AllocsGetResponse) error { 108 if done, err := a.srv.forward("Alloc.GetAllocs", args, args, reply); done { 109 return err 110 } 111 defer metrics.MeasureSince([]string{"nomad", "alloc", "get_allocs"}, time.Now()) 112 113 allocs := make([]*structs.Allocation, len(args.AllocIDs)) 114 115 // Setup the blocking query. We wait for at least one of the requested 116 // allocations to be above the min query index. This guarantees that the 117 // server has received that index. 118 opts := blockingOptions{ 119 queryOpts: &args.QueryOptions, 120 queryMeta: &reply.QueryMeta, 121 run: func(ws memdb.WatchSet, state *state.StateStore) error { 122 // Lookup the allocation 123 thresholdMet := false 124 maxIndex := uint64(0) 125 for i, alloc := range args.AllocIDs { 126 out, err := state.AllocByID(ws, alloc) 127 if err != nil { 128 return err 129 } 130 if out == nil { 131 // We don't have the alloc yet 132 thresholdMet = false 133 break 134 } 135 136 // Store the pointer 137 allocs[i] = out 138 139 // Check if we have passed the minimum index 140 if out.ModifyIndex > args.QueryOptions.MinQueryIndex { 141 thresholdMet = true 142 } 143 144 if maxIndex < out.ModifyIndex { 145 maxIndex = out.ModifyIndex 146 } 147 } 148 149 // Setup the output 150 if thresholdMet { 151 reply.Allocs = allocs 152 reply.Index = maxIndex 153 } else { 154 // Use the last index that affected the nodes table 155 index, err := state.Index("allocs") 156 if err != nil { 157 return err 158 } 159 reply.Index = index 160 } 161 162 // Set the query response 163 a.srv.setQueryMeta(&reply.QueryMeta) 164 return nil 165 }, 166 } 167 return a.srv.blockingRPC(&opts) 168 }