1
// Nova double testing service - HTTP API tests
10
. "launchpad.net/gocheck"
11
"launchpad.net/goose/nova"
12
"launchpad.net/goose/testing/httpsuite"
13
"launchpad.net/goose/testservices/identityservice"
20
type NovaHTTPSuite struct {
26
var _ = Suite(&NovaHTTPSuite{})
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)
36
func (s *NovaHTTPSuite) TearDownSuite(c *C) {
37
s.HTTPSuite.TearDownSuite(c)
40
func (s *NovaHTTPSuite) SetUpTest(c *C) {
41
s.HTTPSuite.SetUpTest(c)
42
s.service.SetupHTTP(s.Mux)
45
func (s *NovaHTTPSuite) TearDownTest(c *C) {
46
s.HTTPSuite.TearDownTest(c)
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()
56
err = json.Unmarshal(body, &expected)
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()
66
expBody := expected.requestBody(resp.Request)
67
// cast to string for easier asserts debugging
68
c.Assert(string(body), Equals, string(expBody))
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, "/")
77
req, err := http.NewRequest(method, url, bytes.NewReader(body))
81
for header, values := range headers {
82
for _, value := range values {
83
req.Header.Add(header, value)
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)
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) {
95
headers = make(http.Header)
97
headers.Set(authToken, s.token)
98
url := s.service.endpointURL(true, path)
99
return s.sendRequest(method, url, body, headers)
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)
109
return s.authRequest(method, path, jsonBody, headers)
112
// setHeader creates http.Header map, sets the given header, and
114
func setHeader(header, value string) http.Header {
115
h := make(http.Header)
120
// SimpleTest defines a simple request without a body and expected response.
121
type SimpleTest struct {
126
expect *errorResponse
129
func (s *NovaHTTPSuite) simpleTests() []SimpleTest {
130
var simpleTests = []SimpleTest{
135
headers: make(http.Header),
136
expect: errUnauthorized,
142
headers: setHeader(authToken, "phony"),
143
expect: errUnauthorized,
149
headers: setHeader(authToken, s.token),
150
expect: errNoVersion,
156
headers: setHeader(authToken, s.token),
157
expect: errMultipleChoices,
162
url: "/any/unknown/one",
163
headers: setHeader(authToken, s.token),
164
expect: errMultipleChoices,
168
url: "/any/unknown/one",
174
url: versionPath + "/phony_token",
175
headers: setHeader(authToken, s.token),
176
expect: errBadRequest,
185
url: "/flavors/invalid",
191
expect: errBadRequest2,
195
url: "/flavors/invalid",
205
url: "/flavors/invalid",
206
expect: errNotFoundJSON,
215
url: "/flavors/invalid",
216
expect: errForbidden,
220
url: "/flavors/detail/invalid",
225
url: "/flavors/detail",
230
url: "/flavors/detail/invalid",
235
url: "/flavors/detail",
236
expect: errNotFoundJSON,
240
url: "/flavors/detail/invalid",
245
url: "/flavors/detail",
246
expect: errForbidden,
250
url: "/flavors/detail/invalid",
255
url: "/servers/invalid",
256
expect: errNotFoundJSON,
261
expect: errBadRequest2,
265
url: "/servers/invalid",
275
url: "/servers/invalid",
276
expect: errBadRequest2,
285
url: "/servers/invalid",
286
expect: errNotFoundJSON,
290
url: "/servers/detail/invalid",
295
url: "/servers/detail",
300
url: "/servers/detail/invalid",
305
url: "/servers/detail",
306
expect: errBadRequest2,
310
url: "/servers/detail/invalid",
315
url: "/servers/detail",
316
expect: errNotFoundJSON,
320
url: "/servers/detail/invalid",
325
url: "/os-security-groups/invalid",
326
expect: errBadRequestSG,
330
url: "/os-security-groups/42",
331
expect: errNotFoundJSONSG,
335
url: "/os-security-groups",
336
expect: errBadRequest2,
340
url: "/os-security-groups/invalid",
345
url: "/os-security-groups",
350
url: "/os-security-groups/invalid",
351
expect: errNotFoundJSON,
355
url: "/os-security-groups",
360
url: "/os-security-groups/invalid",
361
expect: errBadRequestSG,
365
url: "/os-security-groups/42",
366
expect: errNotFoundJSONSG,
370
url: "/os-security-group-rules",
371
expect: errNotFoundJSON,
375
url: "/os-security-group-rules/invalid",
376
expect: errNotFoundJSON,
380
url: "/os-security-group-rules/42",
381
expect: errNotFoundJSON,
385
url: "/os-security-group-rules",
386
expect: errBadRequest2,
390
url: "/os-security-group-rules/invalid",
395
url: "/os-security-group-rules",
400
url: "/os-security-group-rules/invalid",
401
expect: errNotFoundJSON,
405
url: "/os-security-group-rules",
410
url: "/os-security-group-rules/invalid",
411
expect: errBadRequestSG, // sic; should've been rule-specific
415
url: "/os-security-group-rules/42",
416
expect: errNotFoundJSONSGR,
420
url: "/os-floating-ips/42",
421
expect: errNotFoundJSON,
425
url: "/os-floating-ips/invalid",
430
url: "/os-floating-ips",
435
url: "/os-floating-ips/invalid",
436
expect: errNotFoundJSON,
440
url: "/os-floating-ips",
445
url: "/os-floating-ips/invalid",
446
expect: errNotFoundJSON,
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)
465
resp, err = s.sendRequest(t.method, t.url, nil, t.headers)
467
resp, err = s.authRequest(t.method, t.url, nil, t.headers)
470
c.Assert(resp.StatusCode, Equals, t.expect.code)
471
assertBody(c, resp, t.expect)
473
fmt.Printf("total: %d\n", len(simpleTests))
476
func (s *NovaHTTPSuite) TestGetFlavors(c *C) {
477
// The test service has 3 default flavours.
478
var expected struct {
479
Flavors []nova.Entity
481
resp, err := s.authRequest("GET", "/flavors", nil, nil)
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
494
resp, err = s.authRequest("GET", "/flavors/1", nil, nil)
496
c.Assert(resp.StatusCode, Equals, http.StatusOK)
497
assertJSON(c, resp, &expectedFlavor)
498
c.Assert(expectedFlavor.Flavor.Name, Equals, "m1.tiny")
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
508
resp, err := s.authRequest("GET", "/flavors/detail", nil, nil)
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)
518
assertBody(c, resp, errNotFound)
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
527
resp, err := s.authRequest("GET", "/servers", nil, nil)
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"},
536
for i, server := range servers {
537
s.service.buildServerLinks(&server)
539
err := s.service.addServer(server)
541
defer s.service.removeServer(server.Id)
543
entities = s.service.allServersAsEntities(nil)
544
resp, err = s.authRequest("GET", "/servers", nil, nil)
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]
552
c.Assert(expected.Servers, DeepEquals, entities)
553
var expectedServer struct {
554
Server nova.ServerDetail
556
resp, err = s.authRequest("GET", "/servers/sr1", nil, nil)
558
c.Assert(resp.StatusCode, Equals, http.StatusOK)
559
assertJSON(c, resp, &expectedServer)
560
c.Assert(expectedServer.Server, DeepEquals, servers[0])
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
569
url := "/servers?status=RESCUE&status=BUILD&name=srv2&name=srv1"
570
resp, err := s.authRequest("GET", url, nil, nil)
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},
580
for i, server := range servers {
581
s.service.buildServerLinks(&server)
583
err := s.service.addServer(server)
585
defer s.service.removeServer(server.Id)
587
resp, err = s.authRequest("GET", url, nil, nil)
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)
596
func (s *NovaHTTPSuite) TestNewUUID(c *C) {
597
uuid, err := newUUID()
599
var p1, p2, p3, p4, p5 string
600
num, err := fmt.Sscanf(uuid, "%8x-%4x-%4x-%4x-%12x", &p1, &p2, &p3, &p4, &p5)
602
c.Assert(num, Equals, 5)
603
uuid2, err := newUUID()
605
c.Assert(uuid2, Not(Equals), uuid)
608
func (s *NovaHTTPSuite) assertAddresses(c *C, serverId string) {
609
server, err := s.service.server(serverId)
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}`)
626
func (s *NovaHTTPSuite) TestRunServer(c *C) {
627
entities := s.service.allServersAsEntities(nil)
628
c.Assert(entities, HasLen, 0)
631
FlavorRef string `json:"flavorRef"`
632
ImageRef string `json:"imageRef"`
633
Name string `json:"name"`
634
SecurityGroups []map[string]string `json:"security_groups"`
637
resp, err := s.jsonRequest("POST", "/servers", req, nil)
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)
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)
649
c.Assert(resp.StatusCode, Equals, http.StatusBadRequest)
650
assertBody(c, resp, errBadRequestSrvFlavor)
651
req.Server.FlavorRef = "flavor"
652
var expected struct {
654
SecurityGroups []map[string]string `json:"security_groups"`
660
resp, err = s.jsonRequest("POST", "/servers", req, nil)
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)
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{
679
err = s.service.addSecurityGroup(nova.SecurityGroup{Id: 1, Name: "group1"})
681
defer s.service.removeSecurityGroup(1)
682
err = s.service.addSecurityGroup(nova.SecurityGroup{Id: 2, Name: "group2"})
684
defer s.service.removeSecurityGroup(2)
685
resp, err = s.jsonRequest("POST", "/servers", req, nil)
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)
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)
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)
707
defer s.service.removeServer(server.Id)
708
resp, err := s.authRequest("DELETE", "/servers/sr1", nil, nil)
710
c.Assert(resp.StatusCode, Equals, http.StatusNoContent)
711
_, err = s.service.server(server.Id)
712
c.Assert(err, NotNil)
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"`
721
resp, err := s.authRequest("GET", "/servers/detail", nil, nil)
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"},
730
for i, server := range servers {
731
s.service.buildServerLinks(&server)
733
err := s.service.addServer(server)
735
defer s.service.removeServer(server.Id)
737
resp, err = s.authRequest("GET", "/servers/detail", nil, nil)
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]
745
c.Assert(expected.Servers, DeepEquals, servers)
746
resp, err = s.authRequest("GET", "/servers/detail/sr1", nil, nil)
748
assertBody(c, resp, errNotFound)
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"`
757
url := "/servers/detail?status=RESCUE&status=BUILD&name=srv2&name=srv1"
758
resp, err := s.authRequest("GET", url, nil, nil)
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},
768
for i, server := range servers {
769
s.service.buildServerLinks(&server)
771
err := s.service.addServer(server)
773
defer s.service.removeServer(server.Id)
775
resp, err = s.authRequest("GET", url, nil, nil)
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])
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"`
790
resp, err := s.authRequest("GET", "/os-security-groups", nil, nil)
792
c.Assert(resp.StatusCode, Equals, http.StatusOK)
793
assertJSON(c, resp, &expected)
794
c.Assert(expected.Groups, HasLen, 1)
795
groups = []nova.SecurityGroup{
799
TenantId: s.service.TenantId,
800
Rules: []nova.SecurityGroupRule{},
805
TenantId: s.service.TenantId,
806
Rules: []nova.SecurityGroupRule{},
809
for _, group := range groups {
810
err := s.service.addSecurityGroup(group)
812
defer s.service.removeSecurityGroup(group.Id)
814
resp, err = s.authRequest("GET", "/os-security-groups", nil, nil)
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"`
823
resp, err = s.authRequest("GET", "/os-security-groups/1", nil, nil)
825
c.Assert(resp.StatusCode, Equals, http.StatusOK)
826
assertJSON(c, resp, &expectedGroup)
827
c.Assert(expectedGroup.Group, DeepEquals, groups[0])
830
func (s *NovaHTTPSuite) TestAddSecurityGroup(c *C) {
831
group := nova.SecurityGroup{
835
TenantId: s.service.TenantId,
836
Rules: []nova.SecurityGroupRule{},
838
_, err := s.service.securityGroup(group.Id)
839
c.Assert(err, NotNil)
842
Name string `json:"name"`
843
Description string `json:"description"`
844
} `json:"security_group"`
846
req.Group.Name = group.Name
847
req.Group.Description = group.Description
848
var expected struct {
849
Group nova.SecurityGroup `json:"security_group"`
851
resp, err := s.jsonRequest("POST", "/os-security-groups", req, nil)
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)
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)
866
defer s.service.removeSecurityGroup(group.Id)
867
resp, err := s.authRequest("DELETE", "/os-security-groups/1", nil, nil)
869
c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
870
_, err = s.service.securityGroup(group.Id)
871
c.Assert(err, NotNil)
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)
879
defer s.service.removeSecurityGroup(group1.Id)
880
err = s.service.addSecurityGroup(group2)
882
defer s.service.removeSecurityGroup(group2.Id)
883
riIngress := nova.RuleInfo{
890
riGroup := nova.RuleInfo{
891
ParentGroupId: group2.Id,
894
iprange := make(map[string]string)
895
iprange["cidr"] = riIngress.Cidr
896
rule1 := nova.SecurityGroupRule{
898
ParentGroupId: group1.Id,
899
FromPort: &riIngress.FromPort,
900
ToPort: &riIngress.ToPort,
901
IPProtocol: &riIngress.IPProtocol,
904
rule2 := nova.SecurityGroupRule{
906
ParentGroupId: group2.Id,
907
Group: nova.SecurityGroupRef{
909
TenantId: s.service.TenantId,
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)
917
Rule nova.RuleInfo `json:"security_group_rule"`
920
var expected struct {
921
Rule nova.SecurityGroupRule `json:"security_group_rule"`
923
resp, err := s.jsonRequest("POST", "/os-security-group-rules", req, nil)
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)
936
resp, err = s.jsonRequest("POST", "/os-security-group-rules", req, nil)
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)
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)
952
defer s.service.removeSecurityGroup(group1.Id)
953
err = s.service.addSecurityGroup(group2)
955
defer s.service.removeSecurityGroup(group2.Id)
956
riGroup := nova.RuleInfo{
957
ParentGroupId: group2.Id,
960
rule := nova.SecurityGroupRule{
962
ParentGroupId: group2.Id,
963
Group: nova.SecurityGroupRef{
965
TenantId: group1.TenantId,
968
err = s.service.addSecurityGroupRule(rule.Id, riGroup)
970
resp, err := s.authRequest("DELETE", "/os-security-group-rules/1", nil, nil)
972
c.Assert(resp.StatusCode, Equals, http.StatusAccepted)
973
ok := s.service.hasSecurityGroupRule(group2.Id, rule.Id)
974
c.Assert(ok, Equals, false)
977
func (s *NovaHTTPSuite) TestAddServerSecurityGroup(c *C) {
978
group := nova.SecurityGroup{Id: 1, Name: "group"}
979
err := s.service.addSecurityGroup(group)
981
defer s.service.removeSecurityGroup(group.Id)
982
server := nova.ServerDetail{Id: "sr1"}
983
err = s.service.addServer(server)
985
defer s.service.removeServer(server.Id)
986
ok := s.service.hasServerSecurityGroup(server.Id, group.Id)
987
c.Assert(ok, Equals, false)
990
Name string `json:"name"`
991
} `json:"addSecurityGroup"`
993
req.Group.Name = group.Name
994
resp, err := s.jsonRequest("POST", "/servers/"+server.Id+"/action", req, nil)
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)
1003
func (s *NovaHTTPSuite) TestGetServerSecurityGroups(c *C) {
1004
server := nova.ServerDetail{Id: "sr1"}
1005
groups := []nova.SecurityGroup{
1009
TenantId: s.service.TenantId,
1010
Rules: []nova.SecurityGroupRule{},
1015
TenantId: s.service.TenantId,
1016
Rules: []nova.SecurityGroupRule{},
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)
1032
srvGroups = s.service.allServerSecurityGroups(server.Id)
1033
var expected struct {
1034
Groups []nova.SecurityGroup `json:"security_groups"`
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)
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)
1057
Name string `json:"name"`
1058
} `json:"removeSecurityGroup"`
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)
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"`
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)
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"`
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"},
1097
for _, fip := range fips {
1098
err := s.service.addFloatingIP(fip)
1099
defer s.service.removeFloatingIP(fip.Id)
1100
c.Assert(err, IsNil)
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]
1109
c.Assert(expected.IPs, DeepEquals, fips)
1110
var expectedIP struct {
1111
IP nova.FloatingIP `json:"floating_ip"`
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])
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)
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)
1143
AddFloatingIP struct {
1144
Address string `json:"address"`
1145
} `json:"addFloatingIp"`
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)
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)
1170
RemoveFloatingIP struct {
1171
Address string `json:"address"`
1172
} `json:"removeFloatingIp"`
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)