github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/nomad/alloc_endpoint.go (about) 1 package nomad 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/armon/go-metrics" 8 "github.com/hashicorp/go-memdb" 9 "github.com/hashicorp/nomad/nomad/structs" 10 "github.com/hashicorp/nomad/nomad/watch" 11 ) 12 13 // Alloc endpoint is used for manipulating allocations 14 type Alloc struct { 15 srv *Server 16 } 17 18 // List is used to list the allocations in the system 19 func (a *Alloc) List(args *structs.AllocListRequest, reply *structs.AllocListResponse) error { 20 if done, err := a.srv.forward("Alloc.List", args, args, reply); done { 21 return err 22 } 23 defer metrics.MeasureSince([]string{"nomad", "alloc", "list"}, time.Now()) 24 25 // Setup the blocking query 26 opts := blockingOptions{ 27 queryOpts: &args.QueryOptions, 28 queryMeta: &reply.QueryMeta, 29 watch: watch.NewItems(watch.Item{Table: "allocs"}), 30 run: func() error { 31 // Capture all the allocations 32 snap, err := a.srv.fsm.State().Snapshot() 33 if err != nil { 34 return err 35 } 36 var iter memdb.ResultIterator 37 if prefix := args.QueryOptions.Prefix; prefix != "" { 38 iter, err = snap.AllocsByIDPrefix(prefix) 39 } else { 40 iter, err = snap.Allocs() 41 } 42 if err != nil { 43 return err 44 } 45 46 var allocs []*structs.AllocListStub 47 for { 48 raw := iter.Next() 49 if raw == nil { 50 break 51 } 52 alloc := raw.(*structs.Allocation) 53 allocs = append(allocs, alloc.Stub()) 54 } 55 reply.Allocations = allocs 56 57 // Use the last index that affected the jobs table 58 index, err := snap.Index("allocs") 59 if err != nil { 60 return err 61 } 62 reply.Index = index 63 64 // Set the query response 65 a.srv.setQueryMeta(&reply.QueryMeta) 66 return nil 67 }} 68 return a.srv.blockingRPC(&opts) 69 } 70 71 // GetAlloc is used to lookup a particular allocation 72 func (a *Alloc) GetAlloc(args *structs.AllocSpecificRequest, 73 reply *structs.SingleAllocResponse) error { 74 if done, err := a.srv.forward("Alloc.GetAlloc", args, args, reply); done { 75 return err 76 } 77 defer metrics.MeasureSince([]string{"nomad", "alloc", "get_alloc"}, time.Now()) 78 79 // Setup the blocking query 80 opts := blockingOptions{ 81 queryOpts: &args.QueryOptions, 82 queryMeta: &reply.QueryMeta, 83 watch: watch.NewItems(watch.Item{Alloc: args.AllocID}), 84 run: func() error { 85 // Lookup the allocation 86 snap, err := a.srv.fsm.State().Snapshot() 87 if err != nil { 88 return err 89 } 90 out, err := snap.AllocByID(args.AllocID) 91 if err != nil { 92 return err 93 } 94 95 // Setup the output 96 reply.Alloc = out 97 if out != nil { 98 reply.Index = out.ModifyIndex 99 } else { 100 // Use the last index that affected the nodes table 101 index, err := snap.Index("allocs") 102 if err != nil { 103 return err 104 } 105 reply.Index = index 106 } 107 108 // Set the query response 109 a.srv.setQueryMeta(&reply.QueryMeta) 110 return nil 111 }} 112 return a.srv.blockingRPC(&opts) 113 } 114 115 // GetAllocs is used to lookup a set of allocations 116 func (a *Alloc) GetAllocs(args *structs.AllocsGetRequest, 117 reply *structs.AllocsGetResponse) error { 118 if done, err := a.srv.forward("Alloc.GetAllocs", args, args, reply); done { 119 return err 120 } 121 defer metrics.MeasureSince([]string{"nomad", "alloc", "get_alloc"}, time.Now()) 122 123 // Lookup the allocations 124 snap, err := a.srv.fsm.State().Snapshot() 125 if err != nil { 126 return err 127 } 128 129 allocs := make([]*structs.Allocation, len(args.AllocIDs)) 130 for i, alloc := range args.AllocIDs { 131 out, err := snap.AllocByID(alloc) 132 if err != nil { 133 return err 134 } 135 if out == nil { 136 return fmt.Errorf("unknown alloc id %q", alloc) 137 } 138 139 allocs[i] = out 140 if reply.Index < out.ModifyIndex { 141 reply.Index = out.ModifyIndex 142 } 143 } 144 145 // Set the response 146 a.srv.setQueryMeta(&reply.QueryMeta) 147 reply.Allocs = allocs 148 return nil 149 }