@@ -2,17 +2,11 @@ package server
22
33import (
44 "encoding/json"
5- "fmt"
6- "net"
75 "net/http"
8- "net/url"
9- "strconv"
106
117 "github.com/gorilla/mux"
128 "github.com/packethost/packet-api-server/pkg/store"
13- "github.com/packethost/packet-api-server/pkg/util"
149 "github.com/packethost/packngo"
15- "github.com/packethost/packngo/metadata"
1610)
1711
1812// ErrorHandler a handler for errors that can choose to exit or not
@@ -34,26 +28,13 @@ func (p *PacketServer) CreateHandler() http.Handler {
3428 r := mux .NewRouter ()
3529 // list all facilities
3630 r .HandleFunc ("/facilities" , p .allFacilitiesHandler ).Methods ("GET" )
37- // get all volumes for a project
38- r .HandleFunc ("/projects/{projectID}/storage" , p .listVolumesHandler ).Methods ("GET" )
39- // get information about a specific volume
40- r .HandleFunc ("/storage/{volumeID}" , p .getVolumeHandler ).Methods ("GET" )
4131 // create a BGP config for a project
4232 r .HandleFunc ("/projects/{projectID}/bgp-configs" , p .createBGPHandler ).Methods ("POST" )
43- // create a volume for a project
44- r .HandleFunc ("/projects/{projectID}/storage" , p .createVolumeHandler ).Methods ("POST" )
45- // delete a volume
46- r .HandleFunc ("/storage/{volumeID}" , p .deleteVolumeHandler ).Methods ("DELETE" )
47- // attach a volume to a host
48- r .HandleFunc ("/storage/{volumeID}/attachments" , p .volumeAttachHandler ).Methods ("POST" )
49- // detach a volume from a host
50- r .HandleFunc ("/storage/attachments/{attachmentID}" , p .volumeDetachHandler ).Methods ("DELETE" )
5133 // get all devices for a project
5234 r .HandleFunc ("/projects/{projectID}/devices" , p .listDevicesHandler ).Methods ("GET" )
5335 // get a single device
5436 r .HandleFunc ("/devices/{deviceID}" , p .getDeviceHandler ).Methods ("GET" )
5537 // handle metadata requests
56- r .HandleFunc ("/metadata" , p .metadataHandler ).Methods ("GET" )
5738 return r
5839}
5940
@@ -112,191 +93,6 @@ func (p *PacketServer) getDeviceHandler(w http.ResponseWriter, r *http.Request)
11293 http .NotFound (w , r )
11394}
11495
115- // list all volumes for a project
116- func (p * PacketServer ) listVolumesHandler (w http.ResponseWriter , r * http.Request ) {
117- var err error
118-
119- vars := mux .Vars (r )
120- projectID := vars ["projectID" ]
121-
122- // were we asked to limit it?
123- listOpt , err := paramsToListOpts (r .URL .Query ())
124- if err != nil {
125- w .WriteHeader (http .StatusOK )
126- resp := struct {
127- Error string `json:"error"`
128- }{
129- Error : fmt .Sprintf ("invalid query parameters: %v" , err ),
130- }
131- err = json .NewEncoder (w ).Encode (& resp )
132- if err != nil {
133- p .ErrorHandler .Error (err )
134- }
135- return
136- }
137- vols , err := p .Store .ListVolumes (projectID , listOpt )
138- if err != nil {
139- p .ErrorHandler .Error (err )
140- }
141- var resp = struct {
142- Volumes []* packngo.Volume `json:"volumes"`
143- }{
144- Volumes : vols ,
145- }
146- err = json .NewEncoder (w ).Encode (& resp )
147- if err != nil {
148- p .ErrorHandler .Error (err )
149- }
150- }
151-
152- // get information about a specific volume
153- func (p * PacketServer ) getVolumeHandler (w http.ResponseWriter , r * http.Request ) {
154- vars := mux .Vars (r )
155- volID := vars ["volumeID" ]
156- vol , err := p .Store .GetVolume (volID )
157- if err != nil {
158- p .ErrorHandler .Error (err )
159- }
160- if vol != nil {
161- err := json .NewEncoder (w ).Encode (& vol )
162- if err != nil {
163- p .ErrorHandler .Error (err )
164- }
165- return
166- }
167- http .NotFound (w , r )
168- }
169-
170- // delete a volume
171- func (p * PacketServer ) deleteVolumeHandler (w http.ResponseWriter , r * http.Request ) {
172- vars := mux .Vars (r )
173- volID := vars ["volumeID" ]
174- deleted , err := p .Store .DeleteVolume (volID )
175- if err != nil {
176- p .ErrorHandler .Error (err )
177- }
178- if deleted {
179- w .WriteHeader (http .StatusOK )
180- return
181- }
182- http .NotFound (w , r )
183- }
184-
185- // create a volume
186- func (p * PacketServer ) createVolumeHandler (w http.ResponseWriter , r * http.Request ) {
187- // get the info from the body
188- decoder := json .NewDecoder (r .Body )
189- var cvr packngo.VolumeCreateRequest
190- err := decoder .Decode (& cvr )
191- if err != nil {
192- p .ErrorHandler .Error (err )
193- }
194-
195- vol , err := p .Store .CreateVolume (cvr )
196- if err != nil {
197- p .ErrorHandler .Error (err )
198- }
199- w .WriteHeader (http .StatusCreated )
200- err = json .NewEncoder (w ).Encode (& vol )
201- if err != nil {
202- p .ErrorHandler .Error (err )
203- }
204- }
205-
206- // attach volume
207- func (p * PacketServer ) volumeAttachHandler (w http.ResponseWriter , r * http.Request ) {
208- vars := mux .Vars (r )
209- volID := vars ["volumeID" ]
210- // get the device from the body
211- decoder := json .NewDecoder (r .Body )
212- var attachRequest struct {
213- Device string `json:"device_id"`
214- }
215- err := decoder .Decode (& attachRequest )
216- if err != nil {
217- p .ErrorHandler .Error (err )
218- }
219-
220- attachment , err := p .Store .AttachVolume (volID , attachRequest .Device )
221- if err != nil {
222- p .ErrorHandler .Error (err )
223- }
224-
225- if attachment != nil {
226- w .WriteHeader (http .StatusOK )
227- err = json .NewEncoder (w ).Encode (& attachment )
228- if err != nil {
229- p .ErrorHandler .Error (err )
230- }
231- return
232- }
233- http .NotFound (w , r )
234- }
235-
236- // detach volume
237- func (p * PacketServer ) volumeDetachHandler (w http.ResponseWriter , r * http.Request ) {
238- vars := mux .Vars (r )
239- attachID := vars ["attachmentID" ]
240- detached , err := p .Store .DetachVolume (attachID )
241- if err != nil {
242- p .ErrorHandler .Error (err )
243- }
244- if detached {
245- w .WriteHeader (http .StatusOK )
246- }
247- http .NotFound (w , r )
248- }
249-
250- // metadata handler
251- // this is a difficult one, since we are building a generic API server
252- // but the metadata service is meant to assume it already knows the device ID
253- // and it cannot request it from the client sending the http request
254-
255- // for now, we pre-define it for a device to start
256- func (p * PacketServer ) metadataHandler (w http.ResponseWriter , r * http.Request ) {
257- // do not do anything if we do not have a node defined
258- if p .MetadataDevice == "" {
259- http .NotFound (w , r )
260- return
261- }
262- // now find the given device
263- dev , err := p .Store .GetDevice (p .MetadataDevice )
264- if err != nil {
265- p .ErrorHandler .Error (err )
266- }
267- // find the volumes for the given device, find the attachments, get the metadata
268- allVols := dev .Volumes
269- vols := make ([]* metadata.VolumeInfo , 0 , len (allVols ))
270- for _ , v := range allVols {
271- attachment := v .Attachments [0 ]
272- iqn , ips , err := p .Store .GetAttachmentMetadata (attachment .ID )
273- if err != nil {
274- p .ErrorHandler .Error (err )
275- }
276- vols = append (vols , & metadata.VolumeInfo {
277- Name : util .VolumeIDToName (v .ID ),
278- IQN : iqn ,
279- IPs : []net.IP {net .ParseIP (ips [0 ]), net .ParseIP (ips [1 ])},
280- Capacity : struct {
281- Size int `json:"size,string"`
282- Unit string `json:"unit"`
283- }{
284- Size : v .Size ,
285- Unit : "gb" ,
286- },
287- })
288- }
289- var resp = struct {
290- Volumes []* metadata.VolumeInfo `json:"volumes"`
291- }{
292- Volumes : vols ,
293- }
294- err = json .NewEncoder (w ).Encode (& resp )
295- if err != nil {
296- p .ErrorHandler .Error (err )
297- }
298- }
299-
30096// createBGPHandler enable BGP for a project
30197func (p * PacketServer ) createBGPHandler (w http.ResponseWriter , r * http.Request ) {
30298 vars := mux .Vars (r )
@@ -314,26 +110,3 @@ func (p *PacketServer) createBGPHandler(w http.ResponseWriter, r *http.Request)
314110 }
315111 w .WriteHeader (http .StatusCreated )
316112}
317-
318- func paramsToListOpts (params url.Values ) (* packngo.ListOptions , error ) {
319- listOpt := & packngo.ListOptions {}
320- perPage , ok := params ["per_page" ]
321- if ok && len (perPage ) > 0 && perPage [0 ] != "" {
322- count , err := strconv .Atoi (perPage [0 ])
323- // any error converting should be returned
324- if err != nil {
325- return nil , fmt .Errorf ("error converting per_page %s to int: %v" , perPage [0 ], err )
326- }
327- listOpt .PerPage = count
328- }
329- page , ok := params ["page" ]
330- if ok && len (page ) > 0 && page [0 ] != "" {
331- pageNo , err := strconv .Atoi (page [0 ])
332- // any error converting should be returned
333- if err != nil {
334- return nil , fmt .Errorf ("error converting page %s to int: %v" , page [0 ], err )
335- }
336- listOpt .Page = pageNo
337- }
338- return listOpt , nil
339- }
0 commit comments