blob: c9a004f2327c8d24a4de5d8b141e55ae0b8039de [file] [log] [blame]
Samuel A. Falvo IIb5d93f22014-02-21 15:00:20 -08001// +build acceptance
2
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -08003package openstack
4
5import (
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -08006 "crypto/rand"
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -08007 "fmt"
8 "github.com/rackspace/gophercloud/openstack/compute/servers"
9 "github.com/rackspace/gophercloud/openstack/identity"
10 "github.com/rackspace/gophercloud/openstack/utils"
11 "os"
12 "text/tabwriter"
13 "time"
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -080014)
15
16var errTimeout = fmt.Errorf("Timeout.")
17
18type testState struct {
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080019 o identity.AuthOptions
20 a identity.AuthResults
21 sc *identity.ServiceCatalog
22 eps []identity.Endpoint
23 w *tabwriter.Writer
24 imageId string
25 flavorId string
26 region string
27 ep string
28 client *servers.Client
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -080029 createdServer *servers.Server
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080030 gottenServer *servers.Server
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -080031 updatedServer *servers.Server
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -080032 serverName string
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -080033 alternateName string
34}
35
36func setupForList() (*testState, error) {
37 var err error
38
39 ts := new(testState)
40
41 ts.o, err = utils.AuthOptions()
42 if err != nil {
43 return ts, err
44 }
45
46 ts.a, err = identity.Authenticate(ts.o)
47 if err != nil {
48 return ts, err
49 }
50
51 ts.sc, err = identity.GetServiceCatalog(ts.a)
52 if err != nil {
53 return ts, err
54 }
55
56 ts.eps, err = findAllComputeEndpoints(ts.sc)
57 if err != nil {
58 return ts, err
59 }
60
61 ts.w = new(tabwriter.Writer)
62 ts.w.Init(os.Stdout, 2, 8, 2, ' ', 0)
63
64 return ts, nil
65}
66
67func setupForCRUD() (*testState, error) {
68 ts, err := setupForList()
69 if err != nil {
70 return ts, err
71 }
72
73 ts.imageId = os.Getenv("OS_IMAGE_ID")
74 if ts.imageId == "" {
75 return ts, fmt.Errorf("Expected OS_IMAGE_ID environment variable to be set")
76 }
77
78 ts.flavorId = os.Getenv("OS_FLAVOR_ID")
79 if ts.flavorId == "" {
80 return ts, fmt.Errorf("Expected OS_FLAVOR_ID environment variable to be set")
81 }
82
83 ts.region = os.Getenv("OS_REGION_NAME")
84 if ts.region == "" {
85 ts.region = ts.eps[0].Region
86 }
87
88 ts.ep, err = findEndpointForRegion(ts.eps, ts.region)
89 if err != nil {
90 return ts, err
91 }
92
93 return ts, err
94}
95
96func findAllComputeEndpoints(sc *identity.ServiceCatalog) ([]identity.Endpoint, error) {
97 ces, err := sc.CatalogEntries()
98 if err != nil {
99 return nil, err
100 }
101
102 for _, ce := range ces {
103 if ce.Type == "compute" {
104 return ce.Endpoints, nil
105 }
106 }
107
108 return nil, fmt.Errorf("Compute endpoint not found.")
109}
110
111func findEndpointForRegion(eps []identity.Endpoint, r string) (string, error) {
112 for _, ep := range eps {
113 if ep.Region == r {
114 return ep.PublicURL, nil
115 }
116 }
117 return "", fmt.Errorf("Unknown region %s", r)
118}
119
120func countDown(ts *testState, timeout int) (bool, int, error) {
121 if timeout < 1 {
122 return false, 0, errTimeout
123 }
124 time.Sleep(1 * time.Second)
125 timeout--
126
127 gr, err := servers.GetDetail(ts.client, ts.createdServer.Id)
128 if err != nil {
129 return false, timeout, err
130 }
131
132 ts.gottenServer, err = servers.GetServer(gr)
133 if err != nil {
134 return false, timeout, err
135 }
136
137 return true, timeout, nil
138}
139
140func createServer(ts *testState) error {
141 ts.serverName = randomString("ACPTTEST", 16)
142 fmt.Printf("Attempting to create server: %s\n", ts.serverName)
143
144 ts.client = servers.NewClient(ts.ep, ts.a, ts.o)
145
146 cr, err := servers.Create(ts.client, map[string]interface{}{
147 "flavorRef": ts.flavorId,
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -0800148 "imageRef": ts.imageId,
149 "name": ts.serverName,
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -0800150 })
151 if err != nil {
152 return err
153 }
154
155 ts.createdServer, err = servers.GetServer(cr)
156 return err
157}
158
159func waitForStatus(ts *testState, s string) error {
160 var (
161 inProgress bool
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -0800162 timeout int
163 err error
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -0800164 )
165
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -0800166 for inProgress, timeout, err = countDown(ts, 300); inProgress; inProgress, timeout, err = countDown(ts, timeout) {
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -0800167 if ts.gottenServer.Id != ts.createdServer.Id {
168 return fmt.Errorf("created server id (%s) != gotten server id (%s)", ts.createdServer.Id, ts.gottenServer.Id)
169 }
170
171 if ts.gottenServer.Status == s {
172 fmt.Printf("Server created after %d seconds (approximately)\n", 300-timeout)
173 break
174 }
175 }
176
177 if err == errTimeout {
178 fmt.Printf("I'm not waiting around.\n")
179 err = nil
180 }
181
182 return err
183}
184
185func changeServerName(ts *testState) error {
186 var (
187 inProgress bool
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -0800188 timeout int
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -0800189 )
190
191 ts.alternateName = randomString("ACPTTEST", 16)
192 for ts.alternateName == ts.serverName {
193 ts.alternateName = randomString("ACPTTEST", 16)
194 }
195 fmt.Println("Attempting to change server name")
196
197 ur, err := servers.Update(ts.client, ts.createdServer.Id, map[string]interface{}{
198 "name": ts.alternateName,
199 })
200 if err != nil {
201 return err
202 }
203
204 ts.updatedServer, err = servers.GetServer(ur)
205 if err != nil {
206 return err
207 }
208
209 if ts.updatedServer.Id != ts.createdServer.Id {
210 return fmt.Errorf("Expected updated and created server to share the same ID")
211 }
212
Samuel A. Falvo IIe246ac02014-02-13 23:20:09 -0800213 for inProgress, timeout, err = countDown(ts, 300); inProgress; inProgress, timeout, err = countDown(ts, timeout) {
Samuel A. Falvo II0abdb102014-02-13 23:19:26 -0800214 if ts.gottenServer.Id != ts.updatedServer.Id {
215 return fmt.Errorf("Updated server ID (%s) != gotten server ID (%s)", ts.updatedServer.Id, ts.gottenServer.Id)
216 }
217
218 if ts.gottenServer.Name == ts.alternateName {
219 fmt.Printf("Server updated after %d seconds (approximately)\n", 300-timeout)
220 break
221 }
222 }
223
224 if err == errTimeout {
225 fmt.Printf("I'm not waiting around.\n")
226 err = nil
227 }
228
229 return err
230}
231
232// randomString generates a string of given length, but random content.
233// All content will be within the ASCII graphic character set.
234// (Implementation from Even Shaw's contribution on
235// http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go).
236func randomString(prefix string, n int) string {
237 const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
238 var bytes = make([]byte, n)
239 rand.Read(bytes)
240 for i, b := range bytes {
241 bytes[i] = alphanum[b%byte(len(alphanum))]
242 }
243 return prefix + string(bytes)
244}