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