~james-page/ubuntu/raring/juju-core/1.10.0

« back to all changes in this revision

Viewing changes to src/launchpad.net/goose/testservices/novaservice/service_http_test.go

  • Committer: James Page
  • Author(s): James Page
  • Date: 2013-04-24 10:08:07 UTC
  • Revision ID: james.page@canonical.com-20130424100807-bb153yi4shsb4ydh
Tags: upstream-1.10.0
ImportĀ upstreamĀ versionĀ 1.10.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Nova double testing service - HTTP API tests
 
2
 
 
3
package novaservice
 
4
 
 
5
import (
 
6
        "bytes"
 
7
        "encoding/json"
 
8
        "fmt"
 
9
        "io/ioutil"
 
10
        . "launchpad.net/gocheck"
 
11
        "launchpad.net/goose/nova"
 
12
        "launchpad.net/goose/testing/httpsuite"
 
13
        "launchpad.net/goose/testservices/identityservice"
 
14
        "net/http"
 
15
        "sort"
 
16
        "strconv"
 
17
        "strings"
 
18
)
 
19
 
 
20
type NovaHTTPSuite struct {
 
21
        httpsuite.HTTPSuite
 
22
        service *Nova
 
23
        token   string
 
24
}
 
25
 
 
26
var _ = Suite(&NovaHTTPSuite{})
 
27
 
 
28
func (s *NovaHTTPSuite) SetUpSuite(c *C) {
 
29
        s.HTTPSuite.SetUpSuite(c)
 
30
        identityDouble := identityservice.NewUserPass()
 
31
        userInfo := identityDouble.AddUser("fred", "secret", "tenant")
 
32
        s.token = userInfo.Token
 
33
        s.service = New(s.Server.URL, versionPath, userInfo.TenantId, region, identityDouble)
 
34
}
 
35
 
 
36
func (s *NovaHTTPSuite) TearDownSuite(c *C) {
 
37
        s.HTTPSuite.TearDownSuite(c)
 
38
}
 
39
 
 
40
func (s *NovaHTTPSuite) SetUpTest(c *C) {
 
41
        s.HTTPSuite.SetUpTest(c)
 
42
        s.service.SetupHTTP(s.Mux)
 
43
}
 
44
 
 
45
func (s *NovaHTTPSuite) TearDownTest(c *C) {
 
46
        s.HTTPSuite.TearDownTest(c)
 
47
}
 
48
 
 
49
// assertJSON asserts the passed http.Response's body can be
 
50
// unmarshalled into the given expected object, populating it with the
 
51
// successfully parsed data.
 
52
func assertJSON(c *C, resp *http.Response, expected interface{}) {
 
53
        body, err := ioutil.ReadAll(resp.Body)
 
54
        defer resp.Body.Close()
 
55
        c.Assert(err, IsNil)
 
56
        err = json.Unmarshal(body, &expected)
 
57
        c.Assert(err, IsNil)
 
58
}
 
59
 
 
60
// assertBody asserts the passed http.Response's body matches the
 
61
// expected response, replacing any variables in the expected body.
 
62
func assertBody(c *C, resp *http.Response, expected *errorResponse) {
 
63
        body, err := ioutil.ReadAll(resp.Body)
 
64
        defer resp.Body.Close()
 
65
        c.Assert(err, IsNil)
 
66
        expBody := expected.requestBody(resp.Request)
 
67
        // cast to string for easier asserts debugging
 
68
        c.Assert(string(body), Equals, string(expBody))
 
69
}
 
70
 
 
71
// sendRequest constructs an HTTP request from the parameters and
 
72
// sends it, returning the response or an error.
 
73
func (s *NovaHTTPSuite) sendRequest(method, url string, body []byte, headers http.Header) (*http.Response, error) {
 
74
        if !strings.HasPrefix(url, "http") {
 
75
                url = "http://" + s.service.Hostname + strings.TrimLeft(url, "/")
 
76
        }
 
77
        req, err := http.NewRequest(method, url, bytes.NewReader(body))
 
78
        if err != nil {
 
79
                return nil, err
 
80
        }
 
81
        for header, values := range headers {
 
82
                for _, value := range values {
 
83
                        req.Header.Add(header, value)
 
84
                }
 
85
        }
 
86
        // workaround for https://code.google.com/p/go/issues/detail?id=4454
 
87
        req.Header.Set("Content-Length", strconv.Itoa(len(body)))
 
88
        return http.DefaultClient.Do(req)
 
89
}
 
90
 
 
91
// authRequest is a shortcut for sending requests with pre-set token
 
92
// header and correct version prefix and tenant ID in the URL.
 
93
func (s *NovaHTTPSuite) authRequest(method, path string, body []byte, headers http.Header) (*http.Response, error) {
 
94
        if headers == nil {
 
95
                headers = make(http.Header)
 
96
        }
 
97
        headers.Set(authToken, s.token)
 
98
        url := s.service.endpointURL(true, path)
 
99
        return s.sendRequest(method, url, body, headers)
 
100
}
 
101
 
 
102
// jsonRequest serializes the passed body object to JSON and sends a
 
103
// the request with authRequest().
 
104
func (s *NovaHTTPSuite) jsonRequest(method, path string, body interface{}, headers http.Header) (*http.Response, error) {
 
105
        jsonBody, err := json.Marshal(body)
 
106
        if err != nil {
 
107
                return nil, err
 
108
        }
 
109
        return s.authRequest(method, path, jsonBody, headers)
 
110
}
 
111
 
 
112
// setHeader creates http.Header map, sets the given header, and
 
113
// returns the map.
 
114
func setHeader(header, value string) http.Header {
 
115
        h := make(http.Header)
 
116
        h.Set(header, value)
 
117
        return h
 
118
}
 
119
 
 
120
// SimpleTest defines a simple request without a body and expected response.
 
121
type SimpleTest struct {
 
122
        unauth  bool
 
123
        method  string
 
124
        url     string
 
125
        headers http.Header
 
126
        expect  *errorResponse
 
127
}
 
128
 
 
129
func (s *NovaHTTPSuite) simpleTests() []SimpleTest {
 
130
        var simpleTests = []SimpleTest{
 
131
                {
 
132
                        unauth:  true,
 
133
                        method:  "GET",
 
134
                        url:     "/any",
 
135
                        headers: make(http.Header),
 
136
                        expect:  errUnauthorized,
 
137
                },
 
138
                {
 
139
                        unauth:  true,
 
140
                        method:  "POST",
 
141
                        url:     "/any",
 
142
                        headers: setHeader(authToken, "phony"),
 
143
                        expect:  errUnauthorized,
 
144
                },
 
145
                {
 
146
                        unauth:  true,
 
147
                        method:  "GET",
 
148
                        url:     "/",
 
149
                        headers: setHeader(authToken, s.token),
 
150
                        expect:  errNoVersion,
 
151
                },
 
152
                {
 
153
                        unauth:  true,
 
154
                        method:  "GET",
 
155
                        url:     "/any",
 
156
                        headers: setHeader(authToken, s.token),
 
157
                        expect:  errMultipleChoices,
 
158
                },
 
159
                {
 
160
                        unauth:  true,
 
161
                        method:  "POST",
 
162
                        url:     "/any/unknown/one",
 
163
                        headers: setHeader(authToken, s.token),
 
164
                        expect:  errMultipleChoices,
 
165
                },
 
166
                {
 
167
                        method: "POST",
 
168
                        url:    "/any/unknown/one",
 
169
                        expect: errNotFound,
 
170
                },
 
171
                {
 
172
                        unauth:  true,
 
173
                        method:  "GET",
 
174
                        url:     versionPath + "/phony_token",
 
175
                        headers: setHeader(authToken, s.token),
 
176
                        expect:  errBadRequest,
 
177
                },
 
178
                {
 
179
                        method: "GET",
 
180
                        url:    "/flavors/",
 
181
                        expect: errNotFound,
 
182
                },
 
183
                {
 
184
                        method: "GET",
 
185
                        url:    "/flavors/invalid",
 
186
                        expect: errNotFound,
 
187
                },
 
188
                {
 
189
                        method: "POST",
 
190
                        url:    "/flavors",
 
191
                        expect: errBadRequest2,
 
192
                },
 
193
                {
 
194
                        method: "POST",
 
195
                        url:    "/flavors/invalid",
 
196
                        expect: errNotFound,
 
197
                },
 
198
                {
 
199
                        method: "PUT",
 
200
                        url:    "/flavors",
 
201
                        expect: errNotFound,
 
202
                },
 
203
                {
 
204
                        method: "PUT",
 
205
                        url:    "/flavors/invalid",
 
206
                        expect: errNotFoundJSON,
 
207
                },
 
208
                {
 
209
                        method: "DELETE",
 
210
                        url:    "/flavors",
 
211
                        expect: errNotFound,
 
212
                },
 
213
                {
 
214
                        method: "DELETE",
 
215
                        url:    "/flavors/invalid",
 
216
                        expect: errForbidden,
 
217
                },
 
218
                {
 
219
                        method: "GET",
 
220
                        url:    "/flavors/detail/invalid",
 
221
                        expect: errNotFound,
 
222
                },
 
223
                {
 
224
                        method: "POST",
 
225
                        url:    "/flavors/detail",
 
226
                        expect: errNotFound,
 
227
                },
 
228
                {
 
229
                        method: "POST",
 
230
                        url:    "/flavors/detail/invalid",
 
231
                        expect: errNotFound,
 
232
                },
 
233
                {
 
234
                        method: "PUT",
 
235
                        url:    "/flavors/detail",
 
236
                        expect: errNotFoundJSON,
 
237
                },
 
238
                {
 
239
                        method: "PUT",
 
240
                        url:    "/flavors/detail/invalid",
 
241
                        expect: errNotFound,
 
242
                },
 
243
                {
 
244
                        method: "DELETE",
 
245
                        url:    "/flavors/detail",
 
246
                        expect: errForbidden,
 
247
                },
 
248
                {
 
249
                        method: "DELETE",
 
250
                        url:    "/flavors/detail/invalid",
 
251
                        expect: errNotFound,
 
252
                },
 
253
                {
 
254
                        method: "GET",
 
255
                        url:    "/servers/invalid",
 
256
                        expect: errNotFoundJSON,
 
257
                },
 
258
                {
 
259
                        method: "POST",
 
260
                        url:    "/servers",
 
261
                        expect: errBadRequest2,
 
262
                },
 
263
                {
 
264
                        method: "POST",
 
265
                        url:    "/servers/invalid",
 
266
                        expect: errNotFound,
 
267
                },
 
268
                {
 
269
                        method: "PUT",
 
270
                        url:    "/servers",
 
271
                        expect: errNotFound,
 
272
                },
 
273
                {
 
274
                        method: "PUT",
 
275
                        url:    "/servers/invalid",
 
276
                        expect: errBadRequest2,
 
277
                },
 
278
                {
 
279
                        method: "DELETE",
 
280
                        url:    "/servers",
 
281
                        expect: errNotFound,
 
282
                },
 
283
                {
 
284
                        method: "DELETE",
 
285
                        url:    "/servers/invalid",
 
286
                        expect: errNotFoundJSON,
 
287
                },
 
288
                {
 
289
                        method: "GET",
 
290
                        url:    "/servers/detail/invalid",
 
291
                        expect: errNotFound,
 
292
                },
 
293
                {
 
294
                        method: "POST",
 
295
                        url:    "/servers/detail",
 
296
                        expect: errNotFound,
 
297
                },
 
298
                {
 
299
                        method: "POST",
 
300
                        url:    "/servers/detail/invalid",
 
301
                        expect: errNotFound,
 
302
                },
 
303
                {
 
304
                        method: "PUT",
 
305
                        url:    "/servers/detail",
 
306
                        expect: errBadRequest2,
 
307
                },
 
308
                {
 
309
                        method: "PUT",
 
310
                        url:    "/servers/detail/invalid",
 
311
                        expect: errNotFound,
 
312
                },
 
313
                {
 
314
                        method: "DELETE",
 
315
                        url:    "/servers/detail",
 
316
                        expect: errNotFoundJSON,
 
317
                },
 
318
                {
 
319
                        method: "DELETE",
 
320
                        url:    "/servers/detail/invalid",
 
321
                        expect: errNotFound,
 
322
                },
 
323
                {
 
324
                        method: "GET",
 
325
                        url:    "/os-security-groups/invalid",
 
326
                        expect: errBadRequestSG,
 
327
                },
 
328
                {
 
329
                        method: "GET",
 
330
                        url:    "/os-security-groups/42",
 
331
                        expect: errNotFoundJSONSG,
 
332
                },
 
333
                {
 
334
                        method: "POST",
 
335
                        url:    "/os-security-groups",
 
336
                        expect: errBadRequest2,
 
337
                },
 
338
                {
 
339
                        method: "POST",
 
340
                        url:    "/os-security-groups/invalid",
 
341
                        expect: errNotFound,
 
342
                },
 
343
                {
 
344
                        method: "PUT",
 
345
                        url:    "/os-security-groups",
 
346
                        expect: errNotFound,
 
347
                },
 
348
                {
 
349
                        method: "PUT",
 
350
                        url:    "/os-security-groups/invalid",
 
351
                        expect: errNotFoundJSON,
 
352
                },
 
353
                {
 
354
                        method: "DELETE",
 
355
                        url:    "/os-security-groups",
 
356
                        expect: errNotFound,
 
357
                },
 
358
                {
 
359
                        method: "DELETE",
 
360
                        url:    "/os-security-groups/invalid",
 
361
                        expect: errBadRequestSG,
 
362
                },
 
363
                {
 
364
                        method: "DELETE",
 
365
                        url:    "/os-security-groups/42",
 
366
                        expect: errNotFoundJSONSG,
 
367
                },
 
368
                {
 
369
                        method: "GET",
 
370
                        url:    "/os-security-group-rules",
 
371
                        expect: errNotFoundJSON,
 
372
                },
 
373
                {
 
374
                        method: "GET",
 
375
                        url:    "/os-security-group-rules/invalid",
 
376
                        expect: errNotFoundJSON,
 
377
                },
 
378
                {
 
379
                        method: "GET",
 
380
                        url:    "/os-security-group-rules/42",
 
381
                        expect: errNotFoundJSON,
 
382
                },
 
383
                {
 
384
                        method: "POST",
 
385
                        url:    "/os-security-group-rules",
 
386
                        expect: errBadRequest2,
 
387
                },
 
388
                {
 
389
                        method: "POST",
 
390
                        url:    "/os-security-group-rules/invalid",
 
391
                        expect: errNotFound,
 
392
                },
 
393
                {
 
394
                        method: "PUT",
 
395
                        url:    "/os-security-group-rules",
 
396
                        expect: errNotFound,
 
397
                },
 
398
                {
 
399
                        method: "PUT",
 
400
                        url:    "/os-security-group-rules/invalid",
 
401
                        expect: errNotFoundJSON,
 
402
                },
 
403
                {
 
404
                        method: "DELETE",
 
405
                        url:    "/os-security-group-rules",
 
406
                        expect: errNotFound,
 
407
                },
 
408
                {
 
409
                        method: "DELETE",
 
410
                        url:    "/os-security-group-rules/invalid",
 
411
                        expect: errBadRequestSG, // sic; should've been rule-specific
 
412
                },
 
413
                {
 
414
                        method: "DELETE",
 
415
                        url:    "/os-security-group-rules/42",
 
416
                        expect: errNotFoundJSONSGR,
 
417
                },
 
418
                {
 
419
                        method: "GET",
 
420
                        url:    "/os-floating-ips/42",
 
421
                        expect: errNotFoundJSON,
 
422
                },
 
423
                {
 
424
                        method: "POST",
 
425
                        url:    "/os-floating-ips/invalid",
 
426
                        expect: errNotFound,
 
427
                },
 
428
                {
 
429
                        method: "PUT",
 
430
                        url:    "/os-floating-ips",
 
431
                        expect: errNotFound,
 
432
                },
 
433
                {
 
434
                        method: "PUT",
 
435
                        url:    "/os-floating-ips/invalid",
 
436
                        expect: errNotFoundJSON,
 
437
                },
 
438
                {
 
439
                        method: "DELETE",
 
440
                        url:    "/os-floating-ips",
 
441
                        expect: errNotFound,
 
442
                },
 
443
                {
 
444
                        method: "DELETE",
 
445
                        url:    "/os-floating-ips/invalid",
 
446
                        expect: errNotFoundJSON,
 
447
                },
 
448
        }
 
449
        return simpleTests
 
450
}
 
451
 
 
452
func (s *NovaHTTPSuite) TestSimpleRequestTests(c *C) {
 
453
        simpleTests := s.simpleTests()
 
454
        for i, t := range simpleTests {
 
455
                c.Logf("#%d. %s %s -> %d", i, t.method, t.url, t.expect.code)
 
456
                if t.headers == nil {
 
457
                        t.headers = make(http.Header)
 
458
                        t.headers.Set(authToken, s.token)
 
459
                }
 
460
                var (
 
461
                        resp *http.Response
 
462
                        err  error
 
463
                )
 
464
                if t.unauth {
 
465
                        resp, err = s.sendRequest(t.method, t.url, nil, t.headers)
 
466
                } else {
 
467
                        resp, err = s.authRequest(t.method, t.url, nil, t.headers)
 
468
                }
 
469
                c.Assert(err, IsNil)
 
470
                c.Assert(resp.StatusCode, Equals, t.expect.code)
 
471
                assertBody(c, resp, t.expect)
 
472
        }
 
473
        fmt.Printf("total: %d\n", len(simpleTests))
 
474
}
 
475
 
 
476
func (s *NovaHTTPSuite) TestGetFlavors(c *C) {
 
477
        // The test service has 3 default flavours.
 
478
        var expected struct {
 
479
                Flavors []nova.Entity
 
480
        }
 
481
        resp, err := s.authRequest("GET", "/flavors", nil, nil)
 
482
        c.Assert(err, IsNil)
 
483
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
484
        assertJSON(c, resp, &expected)
 
485
        c.Assert(expected.Flavors, HasLen, 3)
 
486
        entities := s.service.allFlavorsAsEntities()
 
487
        c.Assert(entities, HasLen, 3)
 
488
        sort.Sort(nova.EntitySortBy{"Id", expected.Flavors})
 
489
        sort.Sort(nova.EntitySortBy{"Id", entities})
 
490
        c.Assert(expected.Flavors, DeepEquals, entities)
 
491
        var expectedFlavor struct {
 
492
                Flavor nova.FlavorDetail
 
493
        }
 
494
        resp, err = s.authRequest("GET", "/flavors/1", nil, nil)
 
495
        c.Assert(err, IsNil)
 
496
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
497
        assertJSON(c, resp, &expectedFlavor)
 
498
        c.Assert(expectedFlavor.Flavor.Name, Equals, "m1.tiny")
 
499
}
 
500
 
 
501
func (s *NovaHTTPSuite) TestGetFlavorsDetail(c *C) {
 
502
        // The test service has 3 default flavours.
 
503
        flavors := s.service.allFlavors()
 
504
        c.Assert(flavors, HasLen, 3)
 
505
        var expected struct {
 
506
                Flavors []nova.FlavorDetail
 
507
        }
 
508
        resp, err := s.authRequest("GET", "/flavors/detail", nil, nil)
 
509
        c.Assert(err, IsNil)
 
510
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
511
        assertJSON(c, resp, &expected)
 
512
        c.Assert(expected.Flavors, HasLen, 3)
 
513
        sort.Sort(nova.FlavorDetailSortBy{"Id", expected.Flavors})
 
514
        sort.Sort(nova.FlavorDetailSortBy{"Id", flavors})
 
515
        c.Assert(expected.Flavors, DeepEquals, flavors)
 
516
        resp, err = s.authRequest("GET", "/flavors/detail/1", nil, nil)
 
517
        c.Assert(err, IsNil)
 
518
        assertBody(c, resp, errNotFound)
 
519
}
 
520
 
 
521
func (s *NovaHTTPSuite) TestGetServers(c *C) {
 
522
        entities := s.service.allServersAsEntities(nil)
 
523
        c.Assert(entities, HasLen, 0)
 
524
        var expected struct {
 
525
                Servers []nova.Entity
 
526
        }
 
527
        resp, err := s.authRequest("GET", "/servers", nil, nil)
 
528
        c.Assert(err, IsNil)
 
529
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
530
        assertJSON(c, resp, &expected)
 
531
        c.Assert(expected.Servers, HasLen, 0)
 
532
        servers := []nova.ServerDetail{
 
533
                {Id: "sr1", Name: "server 1"},
 
534
                {Id: "sr2", Name: "server 2"},
 
535
        }
 
536
        for i, server := range servers {
 
537
                s.service.buildServerLinks(&server)
 
538
                servers[i] = server
 
539
                err := s.service.addServer(server)
 
540
                c.Assert(err, IsNil)
 
541
                defer s.service.removeServer(server.Id)
 
542
        }
 
543
        entities = s.service.allServersAsEntities(nil)
 
544
        resp, err = s.authRequest("GET", "/servers", nil, nil)
 
545
        c.Assert(err, IsNil)
 
546
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
547
        assertJSON(c, resp, &expected)
 
548
        c.Assert(expected.Servers, HasLen, 2)
 
549
        if expected.Servers[0].Id != entities[0].Id {
 
550
                expected.Servers[0], expected.Servers[1] = expected.Servers[1], expected.Servers[0]
 
551
        }
 
552
        c.Assert(expected.Servers, DeepEquals, entities)
 
553
        var expectedServer struct {
 
554
                Server nova.ServerDetail
 
555
        }
 
556
        resp, err = s.authRequest("GET", "/servers/sr1", nil, nil)
 
557
        c.Assert(err, IsNil)
 
558
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
559
        assertJSON(c, resp, &expectedServer)
 
560
        c.Assert(expectedServer.Server, DeepEquals, servers[0])
 
561
}
 
562
 
 
563
func (s *NovaHTTPSuite) TestGetServersWithFilters(c *C) {
 
564
        entities := s.service.allServersAsEntities(nil)
 
565
        c.Assert(entities, HasLen, 0)
 
566
        var expected struct {
 
567
                Servers []nova.Entity
 
568
        }
 
569
        url := "/servers?status=RESCUE&status=BUILD&name=srv2&name=srv1"
 
570
        resp, err := s.authRequest("GET", url, nil, nil)
 
571
        c.Assert(err, IsNil)
 
572
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
573
        assertJSON(c, resp, &expected)
 
574
        c.Assert(expected.Servers, HasLen, 0)
 
575
        servers := []nova.ServerDetail{
 
576
                {Id: "sr1", Name: "srv1", Status: nova.StatusBuild},
 
577
                {Id: "sr2", Name: "srv2", Status: nova.StatusRescue},
 
578
                {Id: "sr3", Name: "srv3", Status: nova.StatusActive},
 
579
        }
 
580
        for i, server := range servers {
 
581
                s.service.buildServerLinks(&server)
 
582
                servers[i] = server
 
583
                err := s.service.addServer(server)
 
584
                c.Assert(err, IsNil)
 
585
                defer s.service.removeServer(server.Id)
 
586
        }
 
587
        resp, err = s.authRequest("GET", url, nil, nil)
 
588
        c.Assert(err, IsNil)
 
589
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
590
        assertJSON(c, resp, &expected)
 
591
        c.Assert(expected.Servers, HasLen, 1)
 
592
        c.Assert(expected.Servers[0].Id, Equals, servers[0].Id)
 
593
        c.Assert(expected.Servers[0].Name, Equals, servers[0].Name)
 
594
}
 
595
 
 
596
func (s *NovaHTTPSuite) TestNewUUID(c *C) {
 
597
        uuid, err := newUUID()
 
598
        c.Assert(err, IsNil)
 
599
        var p1, p2, p3, p4, p5 string
 
600
        num, err := fmt.Sscanf(uuid, "%8x-%4x-%4x-%4x-%12x", &p1, &p2, &p3, &p4, &p5)
 
601
        c.Assert(err, IsNil)
 
602
        c.Assert(num, Equals, 5)
 
603
        uuid2, err := newUUID()
 
604
        c.Assert(err, IsNil)
 
605
        c.Assert(uuid2, Not(Equals), uuid)
 
606
}
 
607
 
 
608
func (s *NovaHTTPSuite) assertAddresses(c *C, serverId string) {
 
609
        server, err := s.service.server(serverId)
 
610
        c.Assert(err, IsNil)
 
611
        c.Assert(server.Addresses, HasLen, 2)
 
612
        c.Assert(server.Addresses["public"], HasLen, 2)
 
613
        c.Assert(server.Addresses["private"], HasLen, 2)
 
614
        for network, addresses := range server.Addresses {
 
615
                for _, addr := range addresses {
 
616
                        if addr.Version == 4 && network == "public" {
 
617
                                c.Assert(addr.Address, Matches, `127\.10\.0\.\d{1,3}`)
 
618
                        } else if addr.Version == 4 && network == "private" {
 
619
                                c.Assert(addr.Address, Matches, `127\.0\.0\.\d{1,3}`)
 
620
                        }
 
621
                }
 
622
 
 
623
        }
 
624
}
 
625
 
 
626
func (s *NovaHTTPSuite) TestRunServer(c *C) {
 
627
        entities := s.service.allServersAsEntities(nil)
 
628
        c.Assert(entities, HasLen, 0)
 
629
        var req struct {
 
630
                Server struct {
 
631
                        FlavorRef      string              `json:"flavorRef"`
 
632
                        ImageRef       string              `json:"imageRef"`
 
633
                        Name           string              `json:"name"`
 
634
                        SecurityGroups []map[string]string `json:"security_groups"`
 
635
                } `json:"server"`
 
636
        }
 
637
        resp, err := s.jsonRequest("POST", "/servers", req, nil)
 
638
        c.Assert(err, IsNil)
 
639
        c.Assert(resp.StatusCode, Equals, http.StatusBadRequest)
 
640
        assertBody(c, resp, errBadRequestSrvName)
 
641
        req.Server.Name = "srv1"
 
642
        resp, err = s.jsonRequest("POST", "/servers", req, nil)
 
643
        c.Assert(err, IsNil)
 
644
        c.Assert(resp.StatusCode, Equals, http.StatusBadRequest)
 
645
        assertBody(c, resp, errBadRequestSrvImage)
 
646
        req.Server.ImageRef = "image"
 
647
        resp, err = s.jsonRequest("POST", "/servers", req, nil)
 
648
        c.Assert(err, IsNil)
 
649
        c.Assert(resp.StatusCode, Equals, http.StatusBadRequest)
 
650
        assertBody(c, resp, errBadRequestSrvFlavor)
 
651
        req.Server.FlavorRef = "flavor"
 
652
        var expected struct {
 
653
                Server struct {
 
654
                        SecurityGroups []map[string]string `json:"security_groups"`
 
655
                        Id             string
 
656
                        Links          []nova.Link
 
657
                        AdminPass      string
 
658
                }
 
659
        }
 
660
        resp, err = s.jsonRequest("POST", "/servers", req, nil)
 
661
        c.Assert(err, IsNil)
 
662
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
663
        assertJSON(c, resp, &expected)
 
664
        c.Assert(expected.Server.SecurityGroups, HasLen, 1)
 
665
        c.Assert(expected.Server.SecurityGroups[0]["name"], Equals, "default")
 
666
        c.Assert(expected.Server.Id, Not(Equals), "")
 
667
        c.Assert(expected.Server.Links, HasLen, 2)
 
668
        c.Assert(expected.Server.AdminPass, Not(Equals), "")
 
669
        s.assertAddresses(c, expected.Server.Id)
 
670
        srv, err := s.service.server(expected.Server.Id)
 
671
        c.Assert(err, IsNil)
 
672
        c.Assert(srv.Links, DeepEquals, expected.Server.Links)
 
673
        s.service.removeServer(srv.Id)
 
674
        req.Server.Name = "test2"
 
675
        req.Server.SecurityGroups = []map[string]string{
 
676
                {"name": "group1"},
 
677
                {"name": "group2"},
 
678
        }
 
679
        err = s.service.addSecurityGroup(nova.SecurityGroup{Id: 1, Name: "group1"})
 
680
        c.Assert(err, IsNil)
 
681
        defer s.service.removeSecurityGroup(1)
 
682
        err = s.service.addSecurityGroup(nova.SecurityGroup{Id: 2, Name: "group2"})
 
683
        c.Assert(err, IsNil)
 
684
        defer s.service.removeSecurityGroup(2)
 
685
        resp, err = s.jsonRequest("POST", "/servers", req, nil)
 
686
        c.Assert(err, IsNil)
 
687
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
688
        assertJSON(c, resp, &expected)
 
689
        c.Assert(expected.Server.SecurityGroups, DeepEquals, req.Server.SecurityGroups)
 
690
        srv, err = s.service.server(expected.Server.Id)
 
691
        c.Assert(err, IsNil)
 
692
        ok := s.service.hasServerSecurityGroup(srv.Id, 1)
 
693
        c.Assert(ok, Equals, true)
 
694
        ok = s.service.hasServerSecurityGroup(srv.Id, 2)
 
695
        c.Assert(ok, Equals, true)
 
696
        s.service.removeServerSecurityGroup(srv.Id, 1)
 
697
        s.service.removeServerSecurityGroup(srv.Id, 2)
 
698
        s.service.removeServer(srv.Id)
 
699
}
 
700
 
 
701
func (s *NovaHTTPSuite) TestDeleteServer(c *C) {
 
702
        server := nova.ServerDetail{Id: "sr1"}
 
703
        _, err := s.service.server(server.Id)
 
704
        c.Assert(err, NotNil)
 
705
        err = s.service.addServer(server)
 
706
        c.Assert(err, IsNil)
 
707
        defer s.service.removeServer(server.Id)
 
708
        resp, err := s.authRequest("DELETE", "/servers/sr1", nil, nil)
 
709
        c.Assert(err, IsNil)
 
710
        c.Assert(resp.StatusCode, Equals, http.StatusNoContent)
 
711
        _, err = s.service.server(server.Id)
 
712
        c.Assert(err, NotNil)
 
713
}
 
714
 
 
715
func (s *NovaHTTPSuite) TestGetServersDetail(c *C) {
 
716
        servers := s.service.allServers(nil)
 
717
        c.Assert(servers, HasLen, 0)
 
718
        var expected struct {
 
719
                Servers []nova.ServerDetail `json:"servers"`
 
720
        }
 
721
        resp, err := s.authRequest("GET", "/servers/detail", nil, nil)
 
722
        c.Assert(err, IsNil)
 
723
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
724
        assertJSON(c, resp, &expected)
 
725
        c.Assert(expected.Servers, HasLen, 0)
 
726
        servers = []nova.ServerDetail{
 
727
                {Id: "sr1", Name: "server 1"},
 
728
                {Id: "sr2", Name: "server 2"},
 
729
        }
 
730
        for i, server := range servers {
 
731
                s.service.buildServerLinks(&server)
 
732
                servers[i] = server
 
733
                err := s.service.addServer(server)
 
734
                c.Assert(err, IsNil)
 
735
                defer s.service.removeServer(server.Id)
 
736
        }
 
737
        resp, err = s.authRequest("GET", "/servers/detail", nil, nil)
 
738
        c.Assert(err, IsNil)
 
739
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
740
        assertJSON(c, resp, &expected)
 
741
        c.Assert(expected.Servers, HasLen, 2)
 
742
        if expected.Servers[0].Id != servers[0].Id {
 
743
                expected.Servers[0], expected.Servers[1] = expected.Servers[1], expected.Servers[0]
 
744
        }
 
745
        c.Assert(expected.Servers, DeepEquals, servers)
 
746
        resp, err = s.authRequest("GET", "/servers/detail/sr1", nil, nil)
 
747
        c.Assert(err, IsNil)
 
748
        assertBody(c, resp, errNotFound)
 
749
}
 
750
 
 
751
func (s *NovaHTTPSuite) TestGetServersDetailWithFilters(c *C) {
 
752
        servers := s.service.allServers(nil)
 
753
        c.Assert(servers, HasLen, 0)
 
754
        var expected struct {
 
755
                Servers []nova.ServerDetail `json:"servers"`
 
756
        }
 
757
        url := "/servers/detail?status=RESCUE&status=BUILD&name=srv2&name=srv1"
 
758
        resp, err := s.authRequest("GET", url, nil, nil)
 
759
        c.Assert(err, IsNil)
 
760
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
761
        assertJSON(c, resp, &expected)
 
762
        c.Assert(expected.Servers, HasLen, 0)
 
763
        servers = []nova.ServerDetail{
 
764
                {Id: "sr1", Name: "srv1", Status: nova.StatusBuild},
 
765
                {Id: "sr2", Name: "srv2", Status: nova.StatusRescue},
 
766
                {Id: "sr3", Name: "srv3", Status: nova.StatusActive},
 
767
        }
 
768
        for i, server := range servers {
 
769
                s.service.buildServerLinks(&server)
 
770
                servers[i] = server
 
771
                err := s.service.addServer(server)
 
772
                c.Assert(err, IsNil)
 
773
                defer s.service.removeServer(server.Id)
 
774
        }
 
775
        resp, err = s.authRequest("GET", url, nil, nil)
 
776
        c.Assert(err, IsNil)
 
777
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
778
        assertJSON(c, resp, &expected)
 
779
        c.Assert(expected.Servers, HasLen, 1)
 
780
        c.Assert(expected.Servers[0], DeepEquals, servers[0])
 
781
}
 
782
 
 
783
func (s *NovaHTTPSuite) TestGetSecurityGroups(c *C) {
 
784
        // There is always a default security group.
 
785
        groups := s.service.allSecurityGroups()
 
786
        c.Assert(groups, HasLen, 1)
 
787
        var expected struct {
 
788
                Groups []nova.SecurityGroup `json:"security_groups"`
 
789
        }
 
790
        resp, err := s.authRequest("GET", "/os-security-groups", nil, nil)
 
791
        c.Assert(err, IsNil)
 
792
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
793
        assertJSON(c, resp, &expected)
 
794
        c.Assert(expected.Groups, HasLen, 1)
 
795
        groups = []nova.SecurityGroup{
 
796
                {
 
797
                        Id:       1,
 
798
                        Name:     "group 1",
 
799
                        TenantId: s.service.TenantId,
 
800
                        Rules:    []nova.SecurityGroupRule{},
 
801
                },
 
802
                {
 
803
                        Id:       2,
 
804
                        Name:     "group 2",
 
805
                        TenantId: s.service.TenantId,
 
806
                        Rules:    []nova.SecurityGroupRule{},
 
807
                },
 
808
        }
 
809
        for _, group := range groups {
 
810
                err := s.service.addSecurityGroup(group)
 
811
                c.Assert(err, IsNil)
 
812
                defer s.service.removeSecurityGroup(group.Id)
 
813
        }
 
814
        resp, err = s.authRequest("GET", "/os-security-groups", nil, nil)
 
815
        c.Assert(err, IsNil)
 
816
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
817
        assertJSON(c, resp, &expected)
 
818
        c.Assert(expected.Groups, HasLen, len(groups)+1)
 
819
        checkGroupsInList(c, groups, expected.Groups)
 
820
        var expectedGroup struct {
 
821
                Group nova.SecurityGroup `json:"security_group"`
 
822
        }
 
823
        resp, err = s.authRequest("GET", "/os-security-groups/1", nil, nil)
 
824
        c.Assert(err, IsNil)
 
825
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
826
        assertJSON(c, resp, &expectedGroup)
 
827
        c.Assert(expectedGroup.Group, DeepEquals, groups[0])
 
828
}
 
829
 
 
830
func (s *NovaHTTPSuite) TestAddSecurityGroup(c *C) {
 
831
        group := nova.SecurityGroup{
 
832
                Id:          1,
 
833
                Name:        "group 1",
 
834
                Description: "desc",
 
835
                TenantId:    s.service.TenantId,
 
836
                Rules:       []nova.SecurityGroupRule{},
 
837
        }
 
838
        _, err := s.service.securityGroup(group.Id)
 
839
        c.Assert(err, NotNil)
 
840
        var req struct {
 
841
                Group struct {
 
842
                        Name        string `json:"name"`
 
843
                        Description string `json:"description"`
 
844
                } `json:"security_group"`
 
845
        }
 
846
        req.Group.Name = group.Name
 
847
        req.Group.Description = group.Description
 
848
        var expected struct {
 
849
                Group nova.SecurityGroup `json:"security_group"`
 
850
        }
 
851
        resp, err := s.jsonRequest("POST", "/os-security-groups", req, nil)
 
852
        c.Assert(err, IsNil)
 
853
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
854
        assertJSON(c, resp, &expected)
 
855
        c.Assert(expected.Group, DeepEquals, group)
 
856
        err = s.service.removeSecurityGroup(group.Id)
 
857
        c.Assert(err, IsNil)
 
858
}
 
859
 
 
860
func (s *NovaHTTPSuite) TestDeleteSecurityGroup(c *C) {
 
861
        group := nova.SecurityGroup{Id: 1, Name: "group 1"}
 
862
        _, err := s.service.securityGroup(group.Id)
 
863
        c.Assert(err, NotNil)
 
864
        err = s.service.addSecurityGroup(group)
 
865
        c.Assert(err, IsNil)
 
866
        defer s.service.removeSecurityGroup(group.Id)
 
867
        resp, err := s.authRequest("DELETE", "/os-security-groups/1", nil, nil)
 
868
        c.Assert(err, IsNil)
 
869
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
870
        _, err = s.service.securityGroup(group.Id)
 
871
        c.Assert(err, NotNil)
 
872
}
 
873
 
 
874
func (s *NovaHTTPSuite) TestAddSecurityGroupRule(c *C) {
 
875
        group1 := nova.SecurityGroup{Id: 1, Name: "src"}
 
876
        group2 := nova.SecurityGroup{Id: 2, Name: "tgt"}
 
877
        err := s.service.addSecurityGroup(group1)
 
878
        c.Assert(err, IsNil)
 
879
        defer s.service.removeSecurityGroup(group1.Id)
 
880
        err = s.service.addSecurityGroup(group2)
 
881
        c.Assert(err, IsNil)
 
882
        defer s.service.removeSecurityGroup(group2.Id)
 
883
        riIngress := nova.RuleInfo{
 
884
                ParentGroupId: 1,
 
885
                FromPort:      1234,
 
886
                ToPort:        4321,
 
887
                IPProtocol:    "tcp",
 
888
                Cidr:          "1.2.3.4/5",
 
889
        }
 
890
        riGroup := nova.RuleInfo{
 
891
                ParentGroupId: group2.Id,
 
892
                GroupId:       &group1.Id,
 
893
        }
 
894
        iprange := make(map[string]string)
 
895
        iprange["cidr"] = riIngress.Cidr
 
896
        rule1 := nova.SecurityGroupRule{
 
897
                Id:            1,
 
898
                ParentGroupId: group1.Id,
 
899
                FromPort:      &riIngress.FromPort,
 
900
                ToPort:        &riIngress.ToPort,
 
901
                IPProtocol:    &riIngress.IPProtocol,
 
902
                IPRange:       iprange,
 
903
        }
 
904
        rule2 := nova.SecurityGroupRule{
 
905
                Id:            2,
 
906
                ParentGroupId: group2.Id,
 
907
                Group: nova.SecurityGroupRef{
 
908
                        Name:     group1.Name,
 
909
                        TenantId: s.service.TenantId,
 
910
                },
 
911
        }
 
912
        ok := s.service.hasSecurityGroupRule(group1.Id, rule1.Id)
 
913
        c.Assert(ok, Equals, false)
 
914
        ok = s.service.hasSecurityGroupRule(group2.Id, rule2.Id)
 
915
        c.Assert(ok, Equals, false)
 
916
        var req struct {
 
917
                Rule nova.RuleInfo `json:"security_group_rule"`
 
918
        }
 
919
        req.Rule = riIngress
 
920
        var expected struct {
 
921
                Rule nova.SecurityGroupRule `json:"security_group_rule"`
 
922
        }
 
923
        resp, err := s.jsonRequest("POST", "/os-security-group-rules", req, nil)
 
924
        c.Assert(err, IsNil)
 
925
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
926
        assertJSON(c, resp, &expected)
 
927
        c.Assert(expected.Rule.Id, Equals, rule1.Id)
 
928
        c.Assert(expected.Rule.ParentGroupId, Equals, rule1.ParentGroupId)
 
929
        c.Assert(expected.Rule.Group, Equals, nova.SecurityGroupRef{})
 
930
        c.Assert(*expected.Rule.FromPort, Equals, *rule1.FromPort)
 
931
        c.Assert(*expected.Rule.ToPort, Equals, *rule1.ToPort)
 
932
        c.Assert(*expected.Rule.IPProtocol, Equals, *rule1.IPProtocol)
 
933
        c.Assert(expected.Rule.IPRange, DeepEquals, rule1.IPRange)
 
934
        defer s.service.removeSecurityGroupRule(rule1.Id)
 
935
        req.Rule = riGroup
 
936
        resp, err = s.jsonRequest("POST", "/os-security-group-rules", req, nil)
 
937
        c.Assert(err, IsNil)
 
938
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
939
        assertJSON(c, resp, &expected)
 
940
        c.Assert(expected.Rule.Id, Equals, rule2.Id)
 
941
        c.Assert(expected.Rule.ParentGroupId, Equals, rule2.ParentGroupId)
 
942
        c.Assert(expected.Rule.Group, DeepEquals, rule2.Group)
 
943
        err = s.service.removeSecurityGroupRule(rule2.Id)
 
944
        c.Assert(err, IsNil)
 
945
}
 
946
 
 
947
func (s *NovaHTTPSuite) TestDeleteSecurityGroupRule(c *C) {
 
948
        group1 := nova.SecurityGroup{Id: 1, Name: "src"}
 
949
        group2 := nova.SecurityGroup{Id: 2, Name: "tgt"}
 
950
        err := s.service.addSecurityGroup(group1)
 
951
        c.Assert(err, IsNil)
 
952
        defer s.service.removeSecurityGroup(group1.Id)
 
953
        err = s.service.addSecurityGroup(group2)
 
954
        c.Assert(err, IsNil)
 
955
        defer s.service.removeSecurityGroup(group2.Id)
 
956
        riGroup := nova.RuleInfo{
 
957
                ParentGroupId: group2.Id,
 
958
                GroupId:       &group1.Id,
 
959
        }
 
960
        rule := nova.SecurityGroupRule{
 
961
                Id:            1,
 
962
                ParentGroupId: group2.Id,
 
963
                Group: nova.SecurityGroupRef{
 
964
                        Name:     group1.Name,
 
965
                        TenantId: group1.TenantId,
 
966
                },
 
967
        }
 
968
        err = s.service.addSecurityGroupRule(rule.Id, riGroup)
 
969
        c.Assert(err, IsNil)
 
970
        resp, err := s.authRequest("DELETE", "/os-security-group-rules/1", nil, nil)
 
971
        c.Assert(err, IsNil)
 
972
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
973
        ok := s.service.hasSecurityGroupRule(group2.Id, rule.Id)
 
974
        c.Assert(ok, Equals, false)
 
975
}
 
976
 
 
977
func (s *NovaHTTPSuite) TestAddServerSecurityGroup(c *C) {
 
978
        group := nova.SecurityGroup{Id: 1, Name: "group"}
 
979
        err := s.service.addSecurityGroup(group)
 
980
        c.Assert(err, IsNil)
 
981
        defer s.service.removeSecurityGroup(group.Id)
 
982
        server := nova.ServerDetail{Id: "sr1"}
 
983
        err = s.service.addServer(server)
 
984
        c.Assert(err, IsNil)
 
985
        defer s.service.removeServer(server.Id)
 
986
        ok := s.service.hasServerSecurityGroup(server.Id, group.Id)
 
987
        c.Assert(ok, Equals, false)
 
988
        var req struct {
 
989
                Group struct {
 
990
                        Name string `json:"name"`
 
991
                } `json:"addSecurityGroup"`
 
992
        }
 
993
        req.Group.Name = group.Name
 
994
        resp, err := s.jsonRequest("POST", "/servers/"+server.Id+"/action", req, nil)
 
995
        c.Assert(err, IsNil)
 
996
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
997
        ok = s.service.hasServerSecurityGroup(server.Id, group.Id)
 
998
        c.Assert(ok, Equals, true)
 
999
        err = s.service.removeServerSecurityGroup(server.Id, group.Id)
 
1000
        c.Assert(err, IsNil)
 
1001
}
 
1002
 
 
1003
func (s *NovaHTTPSuite) TestGetServerSecurityGroups(c *C) {
 
1004
        server := nova.ServerDetail{Id: "sr1"}
 
1005
        groups := []nova.SecurityGroup{
 
1006
                {
 
1007
                        Id:       1,
 
1008
                        Name:     "group1",
 
1009
                        TenantId: s.service.TenantId,
 
1010
                        Rules:    []nova.SecurityGroupRule{},
 
1011
                },
 
1012
                {
 
1013
                        Id:       2,
 
1014
                        Name:     "group2",
 
1015
                        TenantId: s.service.TenantId,
 
1016
                        Rules:    []nova.SecurityGroupRule{},
 
1017
                },
 
1018
        }
 
1019
        srvGroups := s.service.allServerSecurityGroups(server.Id)
 
1020
        c.Assert(srvGroups, HasLen, 0)
 
1021
        err := s.service.addServer(server)
 
1022
        c.Assert(err, IsNil)
 
1023
        defer s.service.removeServer(server.Id)
 
1024
        for _, group := range groups {
 
1025
                err = s.service.addSecurityGroup(group)
 
1026
                c.Assert(err, IsNil)
 
1027
                defer s.service.removeSecurityGroup(group.Id)
 
1028
                err = s.service.addServerSecurityGroup(server.Id, group.Id)
 
1029
                c.Assert(err, IsNil)
 
1030
                defer s.service.removeServerSecurityGroup(server.Id, group.Id)
 
1031
        }
 
1032
        srvGroups = s.service.allServerSecurityGroups(server.Id)
 
1033
        var expected struct {
 
1034
                Groups []nova.SecurityGroup `json:"security_groups"`
 
1035
        }
 
1036
        resp, err := s.authRequest("GET", "/servers/"+server.Id+"/os-security-groups", nil, nil)
 
1037
        c.Assert(err, IsNil)
 
1038
        assertJSON(c, resp, &expected)
 
1039
        c.Assert(expected.Groups, DeepEquals, groups)
 
1040
}
 
1041
 
 
1042
func (s *NovaHTTPSuite) TestDeleteServerSecurityGroup(c *C) {
 
1043
        group := nova.SecurityGroup{Id: 1, Name: "group"}
 
1044
        err := s.service.addSecurityGroup(group)
 
1045
        c.Assert(err, IsNil)
 
1046
        defer s.service.removeSecurityGroup(group.Id)
 
1047
        server := nova.ServerDetail{Id: "sr1"}
 
1048
        err = s.service.addServer(server)
 
1049
        c.Assert(err, IsNil)
 
1050
        defer s.service.removeServer(server.Id)
 
1051
        ok := s.service.hasServerSecurityGroup(server.Id, group.Id)
 
1052
        c.Assert(ok, Equals, false)
 
1053
        err = s.service.addServerSecurityGroup(server.Id, group.Id)
 
1054
        c.Assert(err, IsNil)
 
1055
        var req struct {
 
1056
                Group struct {
 
1057
                        Name string `json:"name"`
 
1058
                } `json:"removeSecurityGroup"`
 
1059
        }
 
1060
        req.Group.Name = group.Name
 
1061
        resp, err := s.jsonRequest("POST", "/servers/"+server.Id+"/action", req, nil)
 
1062
        c.Assert(err, IsNil)
 
1063
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
1064
        ok = s.service.hasServerSecurityGroup(server.Id, group.Id)
 
1065
        c.Assert(ok, Equals, false)
 
1066
}
 
1067
 
 
1068
func (s *NovaHTTPSuite) TestPostFloatingIP(c *C) {
 
1069
        fip := nova.FloatingIP{Id: 1, IP: "10.0.0.1", Pool: "nova"}
 
1070
        c.Assert(s.service.allFloatingIPs(), HasLen, 0)
 
1071
        var expected struct {
 
1072
                IP nova.FloatingIP `json:"floating_ip"`
 
1073
        }
 
1074
        resp, err := s.authRequest("POST", "/os-floating-ips", nil, nil)
 
1075
        c.Assert(err, IsNil)
 
1076
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
1077
        assertJSON(c, resp, &expected)
 
1078
        c.Assert(expected.IP, DeepEquals, fip)
 
1079
        err = s.service.removeFloatingIP(fip.Id)
 
1080
        c.Assert(err, IsNil)
 
1081
}
 
1082
 
 
1083
func (s *NovaHTTPSuite) TestGetFloatingIPs(c *C) {
 
1084
        c.Assert(s.service.allFloatingIPs(), HasLen, 0)
 
1085
        var expected struct {
 
1086
                IPs []nova.FloatingIP `json:"floating_ips"`
 
1087
        }
 
1088
        resp, err := s.authRequest("GET", "/os-floating-ips", nil, nil)
 
1089
        c.Assert(err, IsNil)
 
1090
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
1091
        assertJSON(c, resp, &expected)
 
1092
        c.Assert(expected.IPs, HasLen, 0)
 
1093
        fips := []nova.FloatingIP{
 
1094
                {Id: 1, IP: "1.2.3.4", Pool: "nova"},
 
1095
                {Id: 2, IP: "4.3.2.1", Pool: "nova"},
 
1096
        }
 
1097
        for _, fip := range fips {
 
1098
                err := s.service.addFloatingIP(fip)
 
1099
                defer s.service.removeFloatingIP(fip.Id)
 
1100
                c.Assert(err, IsNil)
 
1101
        }
 
1102
        resp, err = s.authRequest("GET", "/os-floating-ips", nil, nil)
 
1103
        c.Assert(err, IsNil)
 
1104
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
1105
        assertJSON(c, resp, &expected)
 
1106
        if expected.IPs[0].Id != fips[0].Id {
 
1107
                expected.IPs[0], expected.IPs[1] = expected.IPs[1], expected.IPs[0]
 
1108
        }
 
1109
        c.Assert(expected.IPs, DeepEquals, fips)
 
1110
        var expectedIP struct {
 
1111
                IP nova.FloatingIP `json:"floating_ip"`
 
1112
        }
 
1113
        resp, err = s.authRequest("GET", "/os-floating-ips/1", nil, nil)
 
1114
        c.Assert(err, IsNil)
 
1115
        c.Assert(resp.StatusCode, Equals, http.StatusOK)
 
1116
        assertJSON(c, resp, &expectedIP)
 
1117
        c.Assert(expectedIP.IP, DeepEquals, fips[0])
 
1118
}
 
1119
 
 
1120
func (s *NovaHTTPSuite) TestDeleteFloatingIP(c *C) {
 
1121
        fip := nova.FloatingIP{Id: 1, IP: "10.0.0.1", Pool: "nova"}
 
1122
        err := s.service.addFloatingIP(fip)
 
1123
        c.Assert(err, IsNil)
 
1124
        defer s.service.removeFloatingIP(fip.Id)
 
1125
        resp, err := s.authRequest("DELETE", "/os-floating-ips/1", nil, nil)
 
1126
        c.Assert(err, IsNil)
 
1127
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
1128
        _, err = s.service.floatingIP(fip.Id)
 
1129
        c.Assert(err, NotNil)
 
1130
}
 
1131
 
 
1132
func (s *NovaHTTPSuite) TestAddServerFloatingIP(c *C) {
 
1133
        fip := nova.FloatingIP{Id: 1, IP: "1.2.3.4"}
 
1134
        server := nova.ServerDetail{Id: "sr1"}
 
1135
        err := s.service.addFloatingIP(fip)
 
1136
        c.Assert(err, IsNil)
 
1137
        defer s.service.removeFloatingIP(fip.Id)
 
1138
        err = s.service.addServer(server)
 
1139
        c.Assert(err, IsNil)
 
1140
        defer s.service.removeServer(server.Id)
 
1141
        c.Assert(s.service.hasServerFloatingIP(server.Id, fip.IP), Equals, false)
 
1142
        var req struct {
 
1143
                AddFloatingIP struct {
 
1144
                        Address string `json:"address"`
 
1145
                } `json:"addFloatingIp"`
 
1146
        }
 
1147
        req.AddFloatingIP.Address = fip.IP
 
1148
        resp, err := s.jsonRequest("POST", "/servers/"+server.Id+"/action", req, nil)
 
1149
        c.Assert(err, IsNil)
 
1150
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
1151
        c.Assert(s.service.hasServerFloatingIP(server.Id, fip.IP), Equals, true)
 
1152
        err = s.service.removeServerFloatingIP(server.Id, fip.Id)
 
1153
        c.Assert(err, IsNil)
 
1154
}
 
1155
 
 
1156
func (s *NovaHTTPSuite) TestRemoveServerFloatingIP(c *C) {
 
1157
        fip := nova.FloatingIP{Id: 1, IP: "1.2.3.4"}
 
1158
        server := nova.ServerDetail{Id: "sr1"}
 
1159
        err := s.service.addFloatingIP(fip)
 
1160
        c.Assert(err, IsNil)
 
1161
        defer s.service.removeFloatingIP(fip.Id)
 
1162
        err = s.service.addServer(server)
 
1163
        c.Assert(err, IsNil)
 
1164
        defer s.service.removeServer(server.Id)
 
1165
        err = s.service.addServerFloatingIP(server.Id, fip.Id)
 
1166
        c.Assert(err, IsNil)
 
1167
        defer s.service.removeServerFloatingIP(server.Id, fip.Id)
 
1168
        c.Assert(s.service.hasServerFloatingIP(server.Id, fip.IP), Equals, true)
 
1169
        var req struct {
 
1170
                RemoveFloatingIP struct {
 
1171
                        Address string `json:"address"`
 
1172
                } `json:"removeFloatingIp"`
 
1173
        }
 
1174
        req.RemoveFloatingIP.Address = fip.IP
 
1175
        resp, err := s.jsonRequest("POST", "/servers/"+server.Id+"/action", req, nil)
 
1176
        c.Assert(err, IsNil)
 
1177
        c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
 
1178
        c.Assert(s.service.hasServerFloatingIP(server.Id, fip.IP), Equals, false)
 
1179
}